branch | RCL_3 |
changeset 29 | 567bb019e3e3 |
parent 0 | 0e761a78d257 |
child 30 | 7e817e7e631c |
6:9b2c3c7a1a9c | 29:567bb019e3e3 |
---|---|
97 PAD_PROP_DIRECTION, |
97 PAD_PROP_DIRECTION, |
98 PAD_PROP_TEMPLATE, |
98 PAD_PROP_TEMPLATE, |
99 /* FILL ME */ |
99 /* FILL ME */ |
100 }; |
100 }; |
101 |
101 |
102 static void gst_pad_class_init (GstPadClass * klass); |
102 #define GST_PAD_GET_PRIVATE(obj) \ |
103 static void gst_pad_init (GstPad * pad); |
103 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PAD, GstPadPrivate)) |
104 |
|
105 #define GST_PAD_CHAINLISTFUNC(pad) ((pad)->abidata.ABI.priv->chainlistfunc) |
|
106 |
|
107 struct _GstPadPrivate |
|
108 { |
|
109 GstPadChainListFunction chainlistfunc; |
|
110 }; |
|
111 |
|
104 static void gst_pad_dispose (GObject * object); |
112 static void gst_pad_dispose (GObject * object); |
105 static void gst_pad_finalize (GObject * object); |
113 static void gst_pad_finalize (GObject * object); |
106 static void gst_pad_set_property (GObject * object, guint prop_id, |
114 static void gst_pad_set_property (GObject * object, guint prop_id, |
107 const GValue * value, GParamSpec * pspec); |
115 const GValue * value, GParamSpec * pspec); |
108 static void gst_pad_get_property (GObject * object, guint prop_id, |
116 static void gst_pad_get_property (GObject * object, guint prop_id, |
140 {GST_FLOW_WRONG_STATE, "wrong-state", 0}, |
148 {GST_FLOW_WRONG_STATE, "wrong-state", 0}, |
141 {GST_FLOW_UNEXPECTED, "unexpected", 0}, |
149 {GST_FLOW_UNEXPECTED, "unexpected", 0}, |
142 {GST_FLOW_NOT_NEGOTIATED, "not-negotiated", 0}, |
150 {GST_FLOW_NOT_NEGOTIATED, "not-negotiated", 0}, |
143 {GST_FLOW_ERROR, "error", 0}, |
151 {GST_FLOW_ERROR, "error", 0}, |
144 {GST_FLOW_NOT_SUPPORTED, "not-supported", 0}, |
152 {GST_FLOW_NOT_SUPPORTED, "not-supported", 0}, |
145 {GST_FLOW_CUSTOM_ERROR, "custom-error", 0}, |
153 {GST_FLOW_CUSTOM_ERROR, "custom-error", 0} |
146 |
|
147 {0, NULL, 0} |
|
148 }; |
154 }; |
149 |
155 |
150 /** |
156 /** |
151 * gst_flow_get_name: |
157 * gst_flow_get_name: |
152 * @ret: a #GstFlowReturn to get the name of. |
158 * @ret: a #GstFlowReturn to get the name of. |
164 { |
170 { |
165 gint i; |
171 gint i; |
166 |
172 |
167 ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS); |
173 ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS); |
168 |
174 |
169 for (i = 0; flow_quarks[i].name; i++) { |
175 for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) { |
170 if (ret == flow_quarks[i].ret) |
176 if (ret == flow_quarks[i].ret) |
171 return flow_quarks[i].name; |
177 return flow_quarks[i].name; |
172 } |
178 } |
173 return "unknown"; |
179 return "unknown"; |
174 } |
180 } |
191 { |
197 { |
192 gint i; |
198 gint i; |
193 |
199 |
194 ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS); |
200 ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS); |
195 |
201 |
196 for (i = 0; flow_quarks[i].name; i++) { |
202 for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) { |
197 if (ret == flow_quarks[i].ret) |
203 if (ret == flow_quarks[i].ret) |
198 return flow_quarks[i].quark; |
204 return flow_quarks[i].quark; |
199 } |
205 } |
200 return 0; |
206 return 0; |
201 } |
207 } |
202 #ifdef __SYMBIAN32__ |
208 |
203 EXPORT_C |
209 #define _do_init \ |
204 #endif |
210 { \ |
205 |
211 gint i; \ |
206 |
212 \ |
207 GType |
213 buffer_quark = g_quark_from_static_string ("buffer"); \ |
208 gst_pad_get_type (void) |
214 event_quark = g_quark_from_static_string ("event"); \ |
209 { |
215 \ |
210 static GType gst_pad_type = 0; |
216 for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) { \ |
211 |
217 flow_quarks[i].quark = g_quark_from_static_string (flow_quarks[i].name); \ |
212 if (G_UNLIKELY (gst_pad_type == 0)) { |
218 } \ |
213 static const GTypeInfo pad_info = { |
219 \ |
214 sizeof (GstPadClass), NULL, NULL, |
220 GST_DEBUG_CATEGORY_INIT (debug_dataflow, "GST_DATAFLOW", \ |
215 (GClassInitFunc) gst_pad_class_init, NULL, NULL, |
221 GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "dataflow inside pads"); \ |
216 sizeof (GstPad), |
222 } |
217 0, |
223 |
218 (GInstanceInitFunc) gst_pad_init, NULL |
224 G_DEFINE_TYPE_WITH_CODE (GstPad, gst_pad, GST_TYPE_OBJECT, _do_init); |
219 }; |
|
220 gint i; |
|
221 |
|
222 gst_pad_type = g_type_register_static (GST_TYPE_OBJECT, "GstPad", |
|
223 &pad_info, 0); |
|
224 |
|
225 buffer_quark = g_quark_from_static_string ("buffer"); |
|
226 event_quark = g_quark_from_static_string ("event"); |
|
227 |
|
228 for (i = 0; flow_quarks[i].name; i++) { |
|
229 flow_quarks[i].quark = g_quark_from_static_string (flow_quarks[i].name); |
|
230 } |
|
231 |
|
232 GST_DEBUG_CATEGORY_INIT (debug_dataflow, "GST_DATAFLOW", |
|
233 GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "dataflow inside pads"); |
|
234 } |
|
235 return gst_pad_type; |
|
236 } |
|
237 |
225 |
238 static gboolean |
226 static gboolean |
239 _gst_do_pass_data_accumulator (GSignalInvocationHint * ihint, |
227 _gst_do_pass_data_accumulator (GSignalInvocationHint * ihint, |
240 GValue * return_accu, const GValue * handler_return, gpointer dummy) |
228 GValue * return_accu, const GValue * handler_return, gpointer dummy) |
241 { |
229 { |
259 GObjectClass *gobject_class; |
247 GObjectClass *gobject_class; |
260 GstObjectClass *gstobject_class; |
248 GstObjectClass *gstobject_class; |
261 |
249 |
262 gobject_class = G_OBJECT_CLASS (klass); |
250 gobject_class = G_OBJECT_CLASS (klass); |
263 gstobject_class = GST_OBJECT_CLASS (klass); |
251 gstobject_class = GST_OBJECT_CLASS (klass); |
252 |
|
253 g_type_class_add_private (klass, sizeof (GstPadPrivate)); |
|
264 |
254 |
265 parent_class = g_type_class_peek_parent (klass); |
255 parent_class = g_type_class_peek_parent (klass); |
266 |
256 |
267 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pad_dispose); |
257 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pad_dispose); |
268 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_pad_finalize); |
258 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_pad_finalize); |
322 NULL, gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, |
312 NULL, gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, |
323 GST_TYPE_MINI_OBJECT); |
313 GST_TYPE_MINI_OBJECT); |
324 |
314 |
325 g_object_class_install_property (gobject_class, PAD_PROP_CAPS, |
315 g_object_class_install_property (gobject_class, PAD_PROP_CAPS, |
326 g_param_spec_boxed ("caps", "Caps", "The capabilities of the pad", |
316 g_param_spec_boxed ("caps", "Caps", "The capabilities of the pad", |
327 GST_TYPE_CAPS, G_PARAM_READABLE)); |
317 GST_TYPE_CAPS, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
328 g_object_class_install_property (gobject_class, PAD_PROP_DIRECTION, |
318 g_object_class_install_property (gobject_class, PAD_PROP_DIRECTION, |
329 g_param_spec_enum ("direction", "Direction", "The direction of the pad", |
319 g_param_spec_enum ("direction", "Direction", "The direction of the pad", |
330 GST_TYPE_PAD_DIRECTION, GST_PAD_UNKNOWN, |
320 GST_TYPE_PAD_DIRECTION, GST_PAD_UNKNOWN, |
331 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); |
321 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); |
332 /* FIXME, Make G_PARAM_CONSTRUCT_ONLY when we fix ghostpads. */ |
322 /* FIXME, Make G_PARAM_CONSTRUCT_ONLY when we fix ghostpads. */ |
333 g_object_class_install_property (gobject_class, PAD_PROP_TEMPLATE, |
323 g_object_class_install_property (gobject_class, PAD_PROP_TEMPLATE, |
334 g_param_spec_object ("template", "Template", |
324 g_param_spec_object ("template", "Template", |
335 "The GstPadTemplate of this pad", GST_TYPE_PAD_TEMPLATE, |
325 "The GstPadTemplate of this pad", GST_TYPE_PAD_TEMPLATE, |
336 G_PARAM_READWRITE)); |
326 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
337 |
327 |
338 #ifndef GST_DISABLE_LOADSAVE |
328 #ifndef GST_DISABLE_LOADSAVE |
339 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_pad_save_thyself); |
329 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_pad_save_thyself); |
340 #endif |
330 #endif |
341 gstobject_class->path_string_separator = "."; |
331 gstobject_class->path_string_separator = "."; |
344 } |
334 } |
345 |
335 |
346 static void |
336 static void |
347 gst_pad_init (GstPad * pad) |
337 gst_pad_init (GstPad * pad) |
348 { |
338 { |
339 pad->abidata.ABI.priv = GST_PAD_GET_PRIVATE (pad); |
|
340 |
|
349 GST_PAD_DIRECTION (pad) = GST_PAD_UNKNOWN; |
341 GST_PAD_DIRECTION (pad) = GST_PAD_UNKNOWN; |
350 GST_PAD_PEER (pad) = NULL; |
342 GST_PAD_PEER (pad) = NULL; |
351 |
343 |
352 GST_PAD_CHAINFUNC (pad) = NULL; |
344 GST_PAD_CHAINFUNC (pad) = NULL; |
353 |
345 |
361 GST_PAD_QUERYTYPEFUNC (pad) = |
353 GST_PAD_QUERYTYPEFUNC (pad) = |
362 GST_DEBUG_FUNCPTR (gst_pad_get_query_types_default); |
354 GST_DEBUG_FUNCPTR (gst_pad_get_query_types_default); |
363 GST_PAD_QUERYFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_query_default); |
355 GST_PAD_QUERYFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_query_default); |
364 GST_PAD_INTLINKFUNC (pad) = |
356 GST_PAD_INTLINKFUNC (pad) = |
365 GST_DEBUG_FUNCPTR (gst_pad_get_internal_links_default); |
357 GST_DEBUG_FUNCPTR (gst_pad_get_internal_links_default); |
358 GST_PAD_ITERINTLINKFUNC (pad) = |
|
359 GST_DEBUG_FUNCPTR (gst_pad_iterate_internal_links_default); |
|
360 |
|
366 GST_PAD_ACCEPTCAPSFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_acceptcaps_default); |
361 GST_PAD_ACCEPTCAPSFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_acceptcaps_default); |
367 |
362 |
368 pad->do_buffer_signals = 0; |
363 pad->do_buffer_signals = 0; |
369 pad->do_event_signals = 0; |
364 pad->do_event_signals = 0; |
370 |
365 |
402 |
397 |
403 /* clear the caps */ |
398 /* clear the caps */ |
404 gst_caps_replace (&GST_PAD_CAPS (pad), NULL); |
399 gst_caps_replace (&GST_PAD_CAPS (pad), NULL); |
405 |
400 |
406 gst_pad_set_pad_template (pad, NULL); |
401 gst_pad_set_pad_template (pad, NULL); |
402 |
|
403 if (pad->block_destroy_data && pad->block_data) { |
|
404 pad->block_destroy_data (pad->block_data); |
|
405 pad->block_data = NULL; |
|
406 } |
|
407 |
407 |
408 G_OBJECT_CLASS (parent_class)->dispose (object); |
408 G_OBJECT_CLASS (parent_class)->dispose (object); |
409 } |
409 } |
410 |
410 |
411 static void |
411 static void |
586 |
586 |
587 /* PAD_UNKNOWN is a little silly but we need some sort of |
587 /* PAD_UNKNOWN is a little silly but we need some sort of |
588 * error return value */ |
588 * error return value */ |
589 g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN); |
589 g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN); |
590 |
590 |
591 GST_OBJECT_LOCK (pad); |
|
592 result = GST_PAD_DIRECTION (pad); |
591 result = GST_PAD_DIRECTION (pad); |
593 GST_OBJECT_UNLOCK (pad); |
|
594 |
592 |
595 return result; |
593 return result; |
596 } |
594 } |
597 |
595 |
598 static gboolean |
596 static gboolean |
799 GST_DEBUG_OBJECT (pad, "calling peer"); |
797 GST_DEBUG_OBJECT (pad, "calling peer"); |
800 if (G_UNLIKELY (!gst_pad_activate_pull (peer, active))) |
798 if (G_UNLIKELY (!gst_pad_activate_pull (peer, active))) |
801 goto peer_failed; |
799 goto peer_failed; |
802 gst_object_unref (peer); |
800 gst_object_unref (peer); |
803 } else { |
801 } else { |
804 goto not_linked; |
802 /* there is no peer, this is only fatal when we activate. When we |
803 * deactivate, we must assume the application has unlinked the peer and |
|
804 * will deactivate it eventually. */ |
|
805 if (active) |
|
806 goto not_linked; |
|
807 else |
|
808 GST_DEBUG_OBJECT (pad, "deactivating unlinked pad"); |
|
805 } |
809 } |
806 } else { |
810 } else { |
807 if (G_UNLIKELY (GST_PAD_GETRANGEFUNC (pad) == NULL)) |
811 if (G_UNLIKELY (GST_PAD_GETRANGEFUNC (pad) == NULL)) |
808 goto failure; /* Can't activate pull on a src without a |
812 goto failure; /* Can't activate pull on a src without a |
809 getrange function */ |
813 getrange function */ |
1002 |
1006 |
1003 return result; |
1007 return result; |
1004 } |
1008 } |
1005 |
1009 |
1006 /** |
1010 /** |
1007 * gst_pad_set_blocked_async: |
1011 * gst_pad_set_blocked_async_full: |
1008 * @pad: the #GstPad to block or unblock |
1012 * @pad: the #GstPad to block or unblock |
1009 * @blocked: boolean indicating whether the pad should be blocked or unblocked |
1013 * @blocked: boolean indicating whether the pad should be blocked or unblocked |
1010 * @callback: #GstPadBlockCallback that will be called when the |
1014 * @callback: #GstPadBlockCallback that will be called when the |
1011 * operation succeeds |
1015 * operation succeeds |
1012 * @user_data: user data passed to the callback |
1016 * @user_data: user data passed to the callback |
1017 * @destroy_data: #GDestroyNotify for user_data |
|
1013 * |
1018 * |
1014 * Blocks or unblocks the dataflow on a pad. The provided callback |
1019 * Blocks or unblocks the dataflow on a pad. The provided callback |
1015 * is called when the operation succeeds; this happens right before the next |
1020 * is called when the operation succeeds; this happens right before the next |
1016 * attempt at pushing a buffer on the pad. |
1021 * attempt at pushing a buffer on the pad. |
1017 * |
1022 * |
1024 * |
1029 * |
1025 * Returns: TRUE if the pad could be blocked. This function can fail if the |
1030 * Returns: TRUE if the pad could be blocked. This function can fail if the |
1026 * wrong parameters were passed or the pad was already in the requested state. |
1031 * wrong parameters were passed or the pad was already in the requested state. |
1027 * |
1032 * |
1028 * MT safe. |
1033 * MT safe. |
1034 * |
|
1035 * Since: 0.10.23 |
|
1029 */ |
1036 */ |
1030 #ifdef __SYMBIAN32__ |
1037 #ifdef __SYMBIAN32__ |
1031 EXPORT_C |
1038 EXPORT_C |
1032 #endif |
1039 #endif |
1033 |
1040 |
1034 gboolean |
1041 gboolean |
1035 gst_pad_set_blocked_async (GstPad * pad, gboolean blocked, |
1042 gst_pad_set_blocked_async_full (GstPad * pad, gboolean blocked, |
1036 GstPadBlockCallback callback, gpointer user_data) |
1043 GstPadBlockCallback callback, gpointer user_data, |
1044 GDestroyNotify destroy_data) |
|
1037 { |
1045 { |
1038 gboolean was_blocked = FALSE; |
1046 gboolean was_blocked = FALSE; |
1039 |
1047 |
1040 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
1048 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
1041 |
1049 |
1048 |
1056 |
1049 if (blocked) { |
1057 if (blocked) { |
1050 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocking pad"); |
1058 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocking pad"); |
1051 |
1059 |
1052 GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKED); |
1060 GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKED); |
1061 |
|
1062 if (pad->block_destroy_data && pad->block_data && |
|
1063 pad->block_data != user_data) |
|
1064 pad->block_destroy_data (pad->block_data); |
|
1065 |
|
1053 pad->block_callback = callback; |
1066 pad->block_callback = callback; |
1054 pad->block_data = user_data; |
1067 pad->block_data = user_data; |
1068 pad->block_destroy_data = destroy_data; |
|
1069 pad->abidata.ABI.block_callback_called = FALSE; |
|
1055 if (!callback) { |
1070 if (!callback) { |
1056 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for block"); |
1071 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for block"); |
1057 GST_PAD_BLOCK_WAIT (pad); |
1072 GST_PAD_BLOCK_WAIT (pad); |
1058 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocked"); |
1073 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocked"); |
1059 } |
1074 } |
1060 } else { |
1075 } else { |
1061 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocking pad"); |
1076 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocking pad"); |
1062 |
1077 |
1063 GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKED); |
1078 GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKED); |
1064 |
1079 |
1080 if (pad->block_destroy_data && pad->block_data && |
|
1081 pad->block_data != user_data) |
|
1082 pad->block_destroy_data (pad->block_data); |
|
1083 |
|
1065 pad->block_callback = callback; |
1084 pad->block_callback = callback; |
1066 pad->block_data = user_data; |
1085 pad->block_data = user_data; |
1086 pad->block_destroy_data = destroy_data; |
|
1087 pad->abidata.ABI.block_callback_called = FALSE; |
|
1067 |
1088 |
1068 GST_PAD_BLOCK_BROADCAST (pad); |
1089 GST_PAD_BLOCK_BROADCAST (pad); |
1069 if (!callback) { |
1090 if (!callback) { |
1070 /* no callback, wait for the unblock to happen */ |
1091 /* no callback, wait for the unblock to happen */ |
1071 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for unblock"); |
1092 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for unblock"); |
1086 return FALSE; |
1107 return FALSE; |
1087 } |
1108 } |
1088 } |
1109 } |
1089 |
1110 |
1090 /** |
1111 /** |
1112 * gst_pad_set_blocked_async: |
|
1113 * @pad: the #GstPad to block or unblock |
|
1114 * @blocked: boolean indicating whether the pad should be blocked or unblocked |
|
1115 * @callback: #GstPadBlockCallback that will be called when the |
|
1116 * operation succeeds |
|
1117 * @user_data: user data passed to the callback |
|
1118 * |
|
1119 * Blocks or unblocks the dataflow on a pad. The provided callback |
|
1120 * is called when the operation succeeds; this happens right before the next |
|
1121 * attempt at pushing a buffer on the pad. |
|
1122 * |
|
1123 * This can take a while as the pad can only become blocked when real dataflow |
|
1124 * is happening. |
|
1125 * When the pipeline is stalled, for example in PAUSED, this can |
|
1126 * take an indeterminate amount of time. |
|
1127 * You can pass NULL as the callback to make this call block. Be careful with |
|
1128 * this blocking call as it might not return for reasons stated above. |
|
1129 * |
|
1130 * Returns: TRUE if the pad could be blocked. This function can fail if the |
|
1131 * wrong parameters were passed or the pad was already in the requested state. |
|
1132 * |
|
1133 * MT safe. |
|
1134 */ |
|
1135 #ifdef __SYMBIAN32__ |
|
1136 EXPORT_C |
|
1137 #endif |
|
1138 |
|
1139 gboolean |
|
1140 gst_pad_set_blocked_async (GstPad * pad, gboolean blocked, |
|
1141 GstPadBlockCallback callback, gpointer user_data) |
|
1142 { |
|
1143 return gst_pad_set_blocked_async_full (pad, blocked, |
|
1144 callback, user_data, NULL); |
|
1145 } |
|
1146 |
|
1147 /** |
|
1091 * gst_pad_set_blocked: |
1148 * gst_pad_set_blocked: |
1092 * @pad: the #GstPad to block or unblock |
1149 * @pad: the #GstPad to block or unblock |
1093 * @blocked: boolean indicating we should block or unblock |
1150 * @blocked: boolean indicating we should block or unblock |
1094 * |
1151 * |
1095 * Blocks or unblocks the dataflow on a pad. This function is |
1152 * Blocks or unblocks the dataflow on a pad. This function is |
1260 |
1317 |
1261 void |
1318 void |
1262 gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain) |
1319 gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain) |
1263 { |
1320 { |
1264 g_return_if_fail (GST_IS_PAD (pad)); |
1321 g_return_if_fail (GST_IS_PAD (pad)); |
1265 g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK); |
1322 g_return_if_fail (GST_PAD_IS_SINK (pad)); |
1266 |
1323 |
1267 GST_PAD_CHAINFUNC (pad) = chain; |
1324 GST_PAD_CHAINFUNC (pad) = chain; |
1268 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainfunc set to %s", |
1325 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainfunc set to %s", |
1269 GST_DEBUG_FUNCPTR_NAME (chain)); |
1326 GST_DEBUG_FUNCPTR_NAME (chain)); |
1270 } |
1327 } |
1271 |
1328 |
1272 /** |
1329 /** |
1330 * gst_pad_set_chain_list_function: |
|
1331 * @pad: a sink #GstPad. |
|
1332 * @chainlist: the #GstPadChainListFunction to set. |
|
1333 * |
|
1334 * Sets the given chain list function for the pad. The chainlist function is |
|
1335 * called to process a #GstBufferList input buffer list. See |
|
1336 * #GstPadChainListFunction for more details. |
|
1337 * |
|
1338 * Since: 0.10.24 |
|
1339 */ |
|
1340 #ifdef __SYMBIAN32__ |
|
1341 EXPORT_C |
|
1342 #endif |
|
1343 |
|
1344 void |
|
1345 gst_pad_set_chain_list_function (GstPad * pad, |
|
1346 GstPadChainListFunction chainlist) |
|
1347 { |
|
1348 g_return_if_fail (GST_IS_PAD (pad)); |
|
1349 g_return_if_fail (GST_PAD_IS_SINK (pad)); |
|
1350 |
|
1351 GST_PAD_CHAINLISTFUNC (pad) = chainlist; |
|
1352 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainlistfunc set to %s", |
|
1353 GST_DEBUG_FUNCPTR_NAME (chainlist)); |
|
1354 } |
|
1355 |
|
1356 /** |
|
1273 * gst_pad_set_getrange_function: |
1357 * gst_pad_set_getrange_function: |
1274 * @pad: a source #GstPad. |
1358 * @pad: a source #GstPad. |
1275 * @get: the #GstPadGetRangeFunction to set. |
1359 * @get: the #GstPadGetRangeFunction to set. |
1276 * |
1360 * |
1277 * Sets the given getrange function for the pad. The getrange function is |
1361 * Sets the given getrange function for the pad. The getrange function is |
1284 |
1368 |
1285 void |
1369 void |
1286 gst_pad_set_getrange_function (GstPad * pad, GstPadGetRangeFunction get) |
1370 gst_pad_set_getrange_function (GstPad * pad, GstPadGetRangeFunction get) |
1287 { |
1371 { |
1288 g_return_if_fail (GST_IS_PAD (pad)); |
1372 g_return_if_fail (GST_IS_PAD (pad)); |
1289 g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC); |
1373 g_return_if_fail (GST_PAD_IS_SRC (pad)); |
1290 |
1374 |
1291 GST_PAD_GETRANGEFUNC (pad) = get; |
1375 GST_PAD_GETRANGEFUNC (pad) = get; |
1292 |
1376 |
1293 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "getrangefunc set to %s", |
1377 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "getrangefunc set to %s", |
1294 GST_DEBUG_FUNCPTR_NAME (get)); |
1378 GST_DEBUG_FUNCPTR_NAME (get)); |
1309 void |
1393 void |
1310 gst_pad_set_checkgetrange_function (GstPad * pad, |
1394 gst_pad_set_checkgetrange_function (GstPad * pad, |
1311 GstPadCheckGetRangeFunction check) |
1395 GstPadCheckGetRangeFunction check) |
1312 { |
1396 { |
1313 g_return_if_fail (GST_IS_PAD (pad)); |
1397 g_return_if_fail (GST_IS_PAD (pad)); |
1314 g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC); |
1398 g_return_if_fail (GST_PAD_IS_SRC (pad)); |
1315 |
1399 |
1316 GST_PAD_CHECKGETRANGEFUNC (pad) = check; |
1400 GST_PAD_CHECKGETRANGEFUNC (pad) = check; |
1317 |
1401 |
1318 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "checkgetrangefunc set to %s", |
1402 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "checkgetrangefunc set to %s", |
1319 GST_DEBUG_FUNCPTR_NAME (check)); |
1403 GST_DEBUG_FUNCPTR_NAME (check)); |
1451 |
1535 |
1452 return result; |
1536 return result; |
1453 } |
1537 } |
1454 |
1538 |
1455 /** |
1539 /** |
1540 * gst_pad_set_iterate_internal_links_function: |
|
1541 * @pad: a #GstPad of either direction. |
|
1542 * @iterintlink: the #GstPadIterIntLinkFunction to set. |
|
1543 * |
|
1544 * Sets the given internal link iterator function for the pad. |
|
1545 * |
|
1546 * Since: 0.10.21 |
|
1547 */ |
|
1548 #ifdef __SYMBIAN32__ |
|
1549 EXPORT_C |
|
1550 #endif |
|
1551 |
|
1552 void |
|
1553 gst_pad_set_iterate_internal_links_function (GstPad * pad, |
|
1554 GstPadIterIntLinkFunction iterintlink) |
|
1555 { |
|
1556 g_return_if_fail (GST_IS_PAD (pad)); |
|
1557 |
|
1558 GST_PAD_ITERINTLINKFUNC (pad) = iterintlink; |
|
1559 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link iterator set to %s", |
|
1560 GST_DEBUG_FUNCPTR_NAME (iterintlink)); |
|
1561 } |
|
1562 |
|
1563 /** |
|
1456 * gst_pad_set_internal_link_function: |
1564 * gst_pad_set_internal_link_function: |
1457 * @pad: a #GstPad of either direction. |
1565 * @pad: a #GstPad of either direction. |
1458 * @intlink: the #GstPadIntLinkFunction to set. |
1566 * @intlink: the #GstPadIntLinkFunction to set. |
1459 * |
1567 * |
1460 * Sets the given internal link function for the pad. |
1568 * Sets the given internal link function for the pad. |
1461 */ |
1569 * |
1570 * Deprecated: Use the thread-safe gst_pad_set_iterate_internal_links_function() |
|
1571 */ |
|
1572 #ifndef GST_REMOVE_DEPRECATED |
|
1462 #ifdef __SYMBIAN32__ |
1573 #ifdef __SYMBIAN32__ |
1463 EXPORT_C |
1574 EXPORT_C |
1464 #endif |
1575 #endif |
1465 |
1576 |
1466 void |
1577 void |
1470 |
1581 |
1471 GST_PAD_INTLINKFUNC (pad) = intlink; |
1582 GST_PAD_INTLINKFUNC (pad) = intlink; |
1472 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link set to %s", |
1583 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link set to %s", |
1473 GST_DEBUG_FUNCPTR_NAME (intlink)); |
1584 GST_DEBUG_FUNCPTR_NAME (intlink)); |
1474 } |
1585 } |
1586 #endif /* GST_REMOVE_DEPRECATED */ |
|
1475 |
1587 |
1476 /** |
1588 /** |
1477 * gst_pad_set_link_function: |
1589 * gst_pad_set_link_function: |
1478 * @pad: a #GstPad. |
1590 * @pad: a #GstPad. |
1479 * @link: the #GstPadLinkFunction to set. |
1591 * @link: the #GstPadLinkFunction to set. |
1682 #endif |
1794 #endif |
1683 |
1795 |
1684 gboolean |
1796 gboolean |
1685 gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad) |
1797 gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad) |
1686 { |
1798 { |
1799 gboolean result = FALSE; |
|
1800 GstElement *parent = NULL; |
|
1801 |
|
1687 g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE); |
1802 g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE); |
1803 g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), FALSE); |
|
1688 g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE); |
1804 g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE); |
1805 g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad), FALSE); |
|
1689 |
1806 |
1690 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinking %s:%s(%p) and %s:%s(%p)", |
1807 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinking %s:%s(%p) and %s:%s(%p)", |
1691 GST_DEBUG_PAD_NAME (srcpad), srcpad, |
1808 GST_DEBUG_PAD_NAME (srcpad), srcpad, |
1692 GST_DEBUG_PAD_NAME (sinkpad), sinkpad); |
1809 GST_DEBUG_PAD_NAME (sinkpad), sinkpad); |
1693 |
1810 |
1811 /* We need to notify the parent before taking any pad locks as the bin in |
|
1812 * question might be waiting for a lock on the pad while holding its lock |
|
1813 * that our message will try to take. */ |
|
1814 if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad)))) { |
|
1815 if (GST_IS_ELEMENT (parent)) { |
|
1816 gst_element_post_message (parent, |
|
1817 gst_message_new_structure_change (GST_OBJECT_CAST (srcpad), |
|
1818 GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK, parent, TRUE)); |
|
1819 } else { |
|
1820 gst_object_unref (parent); |
|
1821 parent = NULL; |
|
1822 } |
|
1823 } |
|
1824 |
|
1694 GST_OBJECT_LOCK (srcpad); |
1825 GST_OBJECT_LOCK (srcpad); |
1695 |
1826 |
1696 if (G_UNLIKELY (GST_PAD_DIRECTION (srcpad) != GST_PAD_SRC)) |
|
1697 goto not_srcpad; |
|
1698 |
|
1699 GST_OBJECT_LOCK (sinkpad); |
1827 GST_OBJECT_LOCK (sinkpad); |
1700 |
|
1701 if (G_UNLIKELY (GST_PAD_DIRECTION (sinkpad) != GST_PAD_SINK)) |
|
1702 goto not_sinkpad; |
|
1703 |
1828 |
1704 if (G_UNLIKELY (GST_PAD_PEER (srcpad) != sinkpad)) |
1829 if (G_UNLIKELY (GST_PAD_PEER (srcpad) != sinkpad)) |
1705 goto not_linked_together; |
1830 goto not_linked_together; |
1706 |
1831 |
1707 if (GST_PAD_UNLINKFUNC (srcpad)) { |
1832 if (GST_PAD_UNLINKFUNC (srcpad)) { |
1724 g_signal_emit (G_OBJECT (sinkpad), gst_pad_signals[PAD_UNLINKED], 0, srcpad); |
1849 g_signal_emit (G_OBJECT (sinkpad), gst_pad_signals[PAD_UNLINKED], 0, srcpad); |
1725 |
1850 |
1726 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinked %s:%s and %s:%s", |
1851 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinked %s:%s and %s:%s", |
1727 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); |
1852 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); |
1728 |
1853 |
1729 return TRUE; |
1854 result = TRUE; |
1730 |
1855 |
1731 not_srcpad: |
1856 done: |
1732 { |
1857 if (parent != NULL) { |
1733 g_critical ("pad %s is not a source pad", GST_PAD_NAME (srcpad)); |
1858 gst_element_post_message (parent, |
1734 GST_OBJECT_UNLOCK (srcpad); |
1859 gst_message_new_structure_change (GST_OBJECT_CAST (srcpad), |
1735 return FALSE; |
1860 GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK, parent, FALSE)); |
1736 } |
1861 gst_object_unref (parent); |
1737 not_sinkpad: |
1862 } |
1738 { |
1863 return result; |
1739 g_critical ("pad %s is not a sink pad", GST_PAD_NAME (sinkpad)); |
1864 |
1740 GST_OBJECT_UNLOCK (sinkpad); |
1865 /* ERRORS */ |
1741 GST_OBJECT_UNLOCK (srcpad); |
|
1742 return FALSE; |
|
1743 } |
|
1744 not_linked_together: |
1866 not_linked_together: |
1745 { |
1867 { |
1746 /* we do not emit a warning in this case because unlinking cannot |
1868 /* we do not emit a warning in this case because unlinking cannot |
1747 * be made MT safe.*/ |
1869 * be made MT safe.*/ |
1748 GST_OBJECT_UNLOCK (sinkpad); |
1870 GST_OBJECT_UNLOCK (sinkpad); |
1749 GST_OBJECT_UNLOCK (srcpad); |
1871 GST_OBJECT_UNLOCK (srcpad); |
1750 return FALSE; |
1872 goto done; |
1751 } |
1873 } |
1752 } |
1874 } |
1753 |
1875 |
1754 /** |
1876 /** |
1755 * gst_pad_is_linked: |
1877 * gst_pad_is_linked: |
1798 GST_CAT_DEBUG (GST_CAT_CAPS, "src caps %" GST_PTR_FORMAT, srccaps); |
1920 GST_CAT_DEBUG (GST_CAT_CAPS, "src caps %" GST_PTR_FORMAT, srccaps); |
1799 GST_CAT_DEBUG (GST_CAT_CAPS, "sink caps %" GST_PTR_FORMAT, sinkcaps); |
1921 GST_CAT_DEBUG (GST_CAT_CAPS, "sink caps %" GST_PTR_FORMAT, sinkcaps); |
1800 |
1922 |
1801 /* if we have caps on both pads we can check the intersection. If one |
1923 /* if we have caps on both pads we can check the intersection. If one |
1802 * of the caps is NULL, we return TRUE. */ |
1924 * of the caps is NULL, we return TRUE. */ |
1803 if (srccaps == NULL || sinkcaps == NULL) |
1925 if (G_UNLIKELY (srccaps == NULL || sinkcaps == NULL)) { |
1926 if (srccaps) |
|
1927 gst_caps_unref (srccaps); |
|
1928 if (sinkcaps) |
|
1929 gst_caps_unref (sinkcaps); |
|
1804 goto done; |
1930 goto done; |
1931 } |
|
1805 |
1932 |
1806 icaps = gst_caps_intersect (srccaps, sinkcaps); |
1933 icaps = gst_caps_intersect (srccaps, sinkcaps); |
1807 gst_caps_unref (srccaps); |
1934 gst_caps_unref (srccaps); |
1808 gst_caps_unref (sinkcaps); |
1935 gst_caps_unref (sinkcaps); |
1809 |
1936 |
1907 /* call with the two pads unlocked, when this function returns GST_PAD_LINK_OK, |
2034 /* call with the two pads unlocked, when this function returns GST_PAD_LINK_OK, |
1908 * the two pads will be locked in the srcpad, sinkpad order. */ |
2035 * the two pads will be locked in the srcpad, sinkpad order. */ |
1909 static GstPadLinkReturn |
2036 static GstPadLinkReturn |
1910 gst_pad_link_prepare (GstPad * srcpad, GstPad * sinkpad) |
2037 gst_pad_link_prepare (GstPad * srcpad, GstPad * sinkpad) |
1911 { |
2038 { |
1912 /* generic checks */ |
|
1913 g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED); |
|
1914 g_return_val_if_fail (GST_IS_PAD (sinkpad), GST_PAD_LINK_REFUSED); |
|
1915 |
|
1916 GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s", |
2039 GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s", |
1917 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); |
2040 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); |
1918 |
2041 |
1919 GST_OBJECT_LOCK (srcpad); |
2042 GST_OBJECT_LOCK (srcpad); |
1920 |
2043 |
1921 if (G_UNLIKELY (GST_PAD_DIRECTION (srcpad) != GST_PAD_SRC)) |
|
1922 goto not_srcpad; |
|
1923 |
|
1924 if (G_UNLIKELY (GST_PAD_PEER (srcpad) != NULL)) |
2044 if (G_UNLIKELY (GST_PAD_PEER (srcpad) != NULL)) |
1925 goto src_was_linked; |
2045 goto src_was_linked; |
1926 |
2046 |
1927 GST_OBJECT_LOCK (sinkpad); |
2047 GST_OBJECT_LOCK (sinkpad); |
1928 |
|
1929 if (G_UNLIKELY (GST_PAD_DIRECTION (sinkpad) != GST_PAD_SINK)) |
|
1930 goto not_sinkpad; |
|
1931 |
2048 |
1932 if (G_UNLIKELY (GST_PAD_PEER (sinkpad) != NULL)) |
2049 if (G_UNLIKELY (GST_PAD_PEER (sinkpad) != NULL)) |
1933 goto sink_was_linked; |
2050 goto sink_was_linked; |
1934 |
2051 |
1935 /* check hierarchy, pads can only be linked if the grandparents |
2052 /* check hierarchy, pads can only be linked if the grandparents |
1943 |
2060 |
1944 /* FIXME check pad scheduling for non-empty intersection */ |
2061 /* FIXME check pad scheduling for non-empty intersection */ |
1945 |
2062 |
1946 return GST_PAD_LINK_OK; |
2063 return GST_PAD_LINK_OK; |
1947 |
2064 |
1948 not_srcpad: |
|
1949 { |
|
1950 g_critical ("pad %s is not a source pad", GST_PAD_NAME (srcpad)); |
|
1951 GST_OBJECT_UNLOCK (srcpad); |
|
1952 return GST_PAD_LINK_WRONG_DIRECTION; |
|
1953 } |
|
1954 src_was_linked: |
2065 src_was_linked: |
1955 { |
2066 { |
1956 GST_CAT_INFO (GST_CAT_PADS, "src %s:%s was already linked to %s:%s", |
2067 GST_CAT_INFO (GST_CAT_PADS, "src %s:%s was already linked to %s:%s", |
1957 GST_DEBUG_PAD_NAME (srcpad), |
2068 GST_DEBUG_PAD_NAME (srcpad), |
1958 GST_DEBUG_PAD_NAME (GST_PAD_PEER (srcpad))); |
2069 GST_DEBUG_PAD_NAME (GST_PAD_PEER (srcpad))); |
1959 /* we do not emit a warning in this case because unlinking cannot |
2070 /* we do not emit a warning in this case because unlinking cannot |
1960 * be made MT safe.*/ |
2071 * be made MT safe.*/ |
1961 GST_OBJECT_UNLOCK (srcpad); |
2072 GST_OBJECT_UNLOCK (srcpad); |
1962 return GST_PAD_LINK_WAS_LINKED; |
2073 return GST_PAD_LINK_WAS_LINKED; |
1963 } |
|
1964 not_sinkpad: |
|
1965 { |
|
1966 g_critical ("pad %s is not a sink pad", GST_PAD_NAME (sinkpad)); |
|
1967 GST_OBJECT_UNLOCK (sinkpad); |
|
1968 GST_OBJECT_UNLOCK (srcpad); |
|
1969 return GST_PAD_LINK_WRONG_DIRECTION; |
|
1970 } |
2074 } |
1971 sink_was_linked: |
2075 sink_was_linked: |
1972 { |
2076 { |
1973 GST_CAT_INFO (GST_CAT_PADS, "sink %s:%s was already linked to %s:%s", |
2077 GST_CAT_INFO (GST_CAT_PADS, "sink %s:%s was already linked to %s:%s", |
1974 GST_DEBUG_PAD_NAME (sinkpad), |
2078 GST_DEBUG_PAD_NAME (sinkpad), |
1994 return GST_PAD_LINK_NOFORMAT; |
2098 return GST_PAD_LINK_NOFORMAT; |
1995 } |
2099 } |
1996 } |
2100 } |
1997 |
2101 |
1998 /** |
2102 /** |
2103 * gst_pad_can_link: |
|
2104 * @srcpad: the source #GstPad. |
|
2105 * @sinkpad: the sink #GstPad. |
|
2106 * |
|
2107 * Checks if the source pad and the sink pad are compatible so they can be |
|
2108 * linked. |
|
2109 * |
|
2110 * Returns: TRUE if the pads can be linked. |
|
2111 */ |
|
2112 #ifdef __SYMBIAN32__ |
|
2113 EXPORT_C |
|
2114 #endif |
|
2115 |
|
2116 gboolean |
|
2117 gst_pad_can_link (GstPad * srcpad, GstPad * sinkpad) |
|
2118 { |
|
2119 GstPadLinkReturn result; |
|
2120 |
|
2121 /* generic checks */ |
|
2122 g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE); |
|
2123 g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE); |
|
2124 |
|
2125 GST_CAT_INFO (GST_CAT_PADS, "check if %s:%s can link with %s:%s", |
|
2126 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); |
|
2127 |
|
2128 /* gst_pad_link_prepare does everything for us, we only release the locks |
|
2129 * on the pads that it gets us. If this function returns !OK the locks are not |
|
2130 * taken anymore. */ |
|
2131 result = gst_pad_link_prepare (srcpad, sinkpad); |
|
2132 if (result != GST_PAD_LINK_OK) |
|
2133 goto done; |
|
2134 |
|
2135 GST_OBJECT_UNLOCK (srcpad); |
|
2136 GST_OBJECT_UNLOCK (sinkpad); |
|
2137 |
|
2138 done: |
|
2139 return result == GST_PAD_LINK_OK; |
|
2140 } |
|
2141 |
|
2142 /** |
|
1999 * gst_pad_link: |
2143 * gst_pad_link: |
2000 * @srcpad: the source #GstPad to link. |
2144 * @srcpad: the source #GstPad to link. |
2001 * @sinkpad: the sink #GstPad to link. |
2145 * @sinkpad: the sink #GstPad to link. |
2002 * |
2146 * |
2003 * Links the source pad and the sink pad. |
2147 * Links the source pad and the sink pad. |
2013 |
2157 |
2014 GstPadLinkReturn |
2158 GstPadLinkReturn |
2015 gst_pad_link (GstPad * srcpad, GstPad * sinkpad) |
2159 gst_pad_link (GstPad * srcpad, GstPad * sinkpad) |
2016 { |
2160 { |
2017 GstPadLinkReturn result; |
2161 GstPadLinkReturn result; |
2162 GstElement *parent; |
|
2163 |
|
2164 g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED); |
|
2165 g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), GST_PAD_LINK_WRONG_DIRECTION); |
|
2166 g_return_val_if_fail (GST_IS_PAD (sinkpad), GST_PAD_LINK_REFUSED); |
|
2167 g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad), |
|
2168 GST_PAD_LINK_WRONG_DIRECTION); |
|
2169 |
|
2170 /* Notify the parent early. See gst_pad_unlink for details. */ |
|
2171 if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad)))) { |
|
2172 if (GST_IS_ELEMENT (parent)) { |
|
2173 gst_element_post_message (parent, |
|
2174 gst_message_new_structure_change (GST_OBJECT_CAST (srcpad), |
|
2175 GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, TRUE)); |
|
2176 } else { |
|
2177 gst_object_unref (parent); |
|
2178 parent = NULL; |
|
2179 } |
|
2180 } |
|
2018 |
2181 |
2019 /* prepare will also lock the two pads */ |
2182 /* prepare will also lock the two pads */ |
2020 result = gst_pad_link_prepare (srcpad, sinkpad); |
2183 result = gst_pad_link_prepare (srcpad, sinkpad); |
2021 |
2184 |
2022 if (result != GST_PAD_LINK_OK) |
2185 if (result != GST_PAD_LINK_OK) |
2023 goto prepare_failed; |
2186 goto done; |
2024 |
2187 |
2025 /* must set peers before calling the link function */ |
2188 /* must set peers before calling the link function */ |
2026 GST_PAD_PEER (srcpad) = sinkpad; |
2189 GST_PAD_PEER (srcpad) = sinkpad; |
2027 GST_PAD_PEER (sinkpad) = srcpad; |
2190 GST_PAD_PEER (sinkpad) = srcpad; |
2028 |
2191 |
2064 GST_PAD_PEER (sinkpad) = NULL; |
2227 GST_PAD_PEER (sinkpad) = NULL; |
2065 |
2228 |
2066 GST_OBJECT_UNLOCK (sinkpad); |
2229 GST_OBJECT_UNLOCK (sinkpad); |
2067 GST_OBJECT_UNLOCK (srcpad); |
2230 GST_OBJECT_UNLOCK (srcpad); |
2068 } |
2231 } |
2232 |
|
2233 done: |
|
2234 if (parent) { |
|
2235 gst_element_post_message (parent, |
|
2236 gst_message_new_structure_change (GST_OBJECT_CAST (srcpad), |
|
2237 GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, FALSE)); |
|
2238 gst_object_unref (parent); |
|
2239 } |
|
2240 |
|
2069 return result; |
2241 return result; |
2070 |
|
2071 prepare_failed: |
|
2072 { |
|
2073 return result; |
|
2074 } |
|
2075 } |
2242 } |
2076 |
2243 |
2077 static void |
2244 static void |
2078 gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ) |
2245 gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ) |
2079 { |
2246 { |
2192 * gst_pad_get_caps: |
2359 * gst_pad_get_caps: |
2193 * @pad: a #GstPad to get the capabilities of. |
2360 * @pad: a #GstPad to get the capabilities of. |
2194 * |
2361 * |
2195 * Gets the capabilities this pad can produce or consume. |
2362 * Gets the capabilities this pad can produce or consume. |
2196 * Note that this method doesn't necessarily return the caps set by |
2363 * Note that this method doesn't necessarily return the caps set by |
2197 * gst_pad_set_caps() - use #GST_PAD_CAPS for that instead. |
2364 * gst_pad_set_caps() - use GST_PAD_CAPS() for that instead. |
2198 * gst_pad_get_caps returns all possible caps a pad can operate with, using |
2365 * gst_pad_get_caps returns all possible caps a pad can operate with, using |
2199 * the pad's get_caps function; |
2366 * the pad's get_caps function; |
2200 * this returns the pad template caps if not explicitly set. |
2367 * this returns the pad template caps if not explicitly set. |
2201 * |
2368 * |
2202 * Returns: a newly allocated copy of the #GstCaps of this pad. |
2369 * Returns: a newly allocated copy of the #GstCaps of this pad. |
2298 if (!fixate_value (dest, &temp)) |
2465 if (!fixate_value (dest, &temp)) |
2299 gst_value_init_and_copy (dest, &temp); |
2466 gst_value_init_and_copy (dest, &temp); |
2300 g_value_unset (&temp); |
2467 g_value_unset (&temp); |
2301 } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) { |
2468 } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) { |
2302 gboolean res = FALSE; |
2469 gboolean res = FALSE; |
2303 guint n; |
2470 guint n, len; |
2304 |
2471 |
2472 len = gst_value_array_get_size (src); |
|
2305 g_value_init (dest, GST_TYPE_ARRAY); |
2473 g_value_init (dest, GST_TYPE_ARRAY); |
2306 for (n = 0; n < gst_value_array_get_size (src); n++) { |
2474 for (n = 0; n < len; n++) { |
2307 GValue kid = { 0 }; |
2475 GValue kid = { 0 }; |
2308 const GValue *orig_kid = gst_value_array_get_value (src, n); |
2476 const GValue *orig_kid = gst_value_array_get_value (src, n); |
2309 |
2477 |
2310 if (!fixate_value (&kid, orig_kid)) |
2478 if (!fixate_value (&kid, orig_kid)) |
2311 gst_value_init_and_copy (&kid, orig_kid); |
2479 gst_value_init_and_copy (&kid, orig_kid); |
2354 |
2522 |
2355 void |
2523 void |
2356 gst_pad_fixate_caps (GstPad * pad, GstCaps * caps) |
2524 gst_pad_fixate_caps (GstPad * pad, GstCaps * caps) |
2357 { |
2525 { |
2358 GstPadFixateCapsFunction fixatefunc; |
2526 GstPadFixateCapsFunction fixatefunc; |
2359 guint n; |
2527 guint n, len; |
2360 |
2528 |
2361 g_return_if_fail (GST_IS_PAD (pad)); |
2529 g_return_if_fail (GST_IS_PAD (pad)); |
2362 g_return_if_fail (caps != NULL); |
2530 g_return_if_fail (caps != NULL); |
2363 |
2531 |
2364 if (gst_caps_is_fixed (caps)) |
2532 if (gst_caps_is_fixed (caps)) |
2368 if (fixatefunc) { |
2536 if (fixatefunc) { |
2369 fixatefunc (pad, caps); |
2537 fixatefunc (pad, caps); |
2370 } |
2538 } |
2371 |
2539 |
2372 /* default fixation */ |
2540 /* default fixation */ |
2373 for (n = 0; n < gst_caps_get_size (caps); n++) { |
2541 len = gst_caps_get_size (caps); |
2542 for (n = 0; n < len; n++) { |
|
2374 GstStructure *s = gst_caps_get_structure (caps, n); |
2543 GstStructure *s = gst_caps_get_structure (caps, n); |
2375 |
2544 |
2376 gst_structure_foreach (s, gst_pad_default_fixate, s); |
2545 gst_structure_foreach (s, gst_pad_default_fixate, s); |
2377 } |
2546 } |
2378 } |
2547 } |
2399 intersect = gst_caps_intersect (allowed, caps); |
2568 intersect = gst_caps_intersect (allowed, caps); |
2400 |
2569 |
2401 GST_DEBUG_OBJECT (pad, "intersection %" GST_PTR_FORMAT, intersect); |
2570 GST_DEBUG_OBJECT (pad, "intersection %" GST_PTR_FORMAT, intersect); |
2402 |
2571 |
2403 result = !gst_caps_is_empty (intersect); |
2572 result = !gst_caps_is_empty (intersect); |
2404 if (!result) |
|
2405 GST_DEBUG_OBJECT (pad, "intersection gave empty caps"); |
|
2406 |
2573 |
2407 gst_caps_unref (allowed); |
2574 gst_caps_unref (allowed); |
2408 gst_caps_unref (intersect); |
2575 gst_caps_unref (intersect); |
2409 |
2576 |
2410 return result; |
2577 return result; |
2443 if (caps == NULL) |
2610 if (caps == NULL) |
2444 return TRUE; |
2611 return TRUE; |
2445 |
2612 |
2446 /* lock for checking the existing caps */ |
2613 /* lock for checking the existing caps */ |
2447 GST_OBJECT_LOCK (pad); |
2614 GST_OBJECT_LOCK (pad); |
2448 acceptfunc = GST_PAD_ACCEPTCAPSFUNC (pad); |
|
2449 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %p", caps); |
2615 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %p", caps); |
2450 /* The current caps on a pad are trivially acceptable */ |
2616 /* The current caps on a pad are trivially acceptable */ |
2451 if (G_LIKELY ((existing = GST_PAD_CAPS (pad)))) { |
2617 if (G_LIKELY ((existing = GST_PAD_CAPS (pad)))) { |
2452 if (caps == existing || gst_caps_is_equal (caps, existing)) |
2618 if (caps == existing || gst_caps_is_equal (caps, existing)) |
2453 goto is_same_caps; |
2619 goto is_same_caps; |
2454 } |
2620 } |
2621 acceptfunc = GST_PAD_ACCEPTCAPSFUNC (pad); |
|
2455 GST_OBJECT_UNLOCK (pad); |
2622 GST_OBJECT_UNLOCK (pad); |
2456 |
2623 |
2457 if (G_LIKELY (acceptfunc)) { |
2624 if (G_LIKELY (acceptfunc)) { |
2458 /* we can call the function */ |
2625 /* we can call the function */ |
2459 result = acceptfunc (pad, caps); |
2626 result = acceptfunc (pad, caps); |
2501 |
2668 |
2502 peerpad = GST_PAD_PEER (pad); |
2669 peerpad = GST_PAD_PEER (pad); |
2503 if (G_UNLIKELY (peerpad == NULL)) |
2670 if (G_UNLIKELY (peerpad == NULL)) |
2504 goto no_peer; |
2671 goto no_peer; |
2505 |
2672 |
2673 gst_object_ref (peerpad); |
|
2674 /* release lock before calling external methods but keep ref to pad */ |
|
2675 GST_OBJECT_UNLOCK (pad); |
|
2676 |
|
2506 result = gst_pad_accept_caps (peerpad, caps); |
2677 result = gst_pad_accept_caps (peerpad, caps); |
2507 GST_OBJECT_UNLOCK (pad); |
2678 |
2679 gst_object_unref (peerpad); |
|
2508 |
2680 |
2509 return result; |
2681 return result; |
2510 |
2682 |
2511 no_peer: |
2683 no_peer: |
2512 { |
2684 { |
2632 static gboolean |
2804 static gboolean |
2633 gst_pad_configure_src (GstPad * pad, GstCaps * caps, gboolean dosetcaps) |
2805 gst_pad_configure_src (GstPad * pad, GstCaps * caps, gboolean dosetcaps) |
2634 { |
2806 { |
2635 gboolean res; |
2807 gboolean res; |
2636 |
2808 |
2637 /* See if pad accepts the caps */ |
2809 if (dosetcaps) { |
2638 if (!gst_pad_accept_caps (pad, caps)) |
2810 /* See if pad accepts the caps */ |
2639 goto not_accepted; |
2811 if (!gst_pad_accept_caps (pad, caps)) |
2640 |
2812 goto not_accepted; |
2641 if (dosetcaps) |
2813 |
2642 res = gst_pad_set_caps (pad, caps); |
2814 res = gst_pad_set_caps (pad, caps); |
2643 else |
2815 } else { |
2644 res = TRUE; |
2816 res = TRUE; |
2645 |
2817 } |
2646 return res; |
2818 return res; |
2647 |
2819 |
2648 not_accepted: |
2820 not_accepted: |
2649 { |
2821 { |
2650 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, |
2822 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, |
2860 * not possible. */ |
3032 * not possible. */ |
2861 if (G_LIKELY (bufferallocfunc == NULL)) |
3033 if (G_LIKELY (bufferallocfunc == NULL)) |
2862 goto fallback; |
3034 goto fallback; |
2863 |
3035 |
2864 ret = bufferallocfunc (pad, offset, size, caps, buf); |
3036 ret = bufferallocfunc (pad, offset, size, caps, buf); |
3037 |
|
2865 if (G_UNLIKELY (ret != GST_FLOW_OK)) |
3038 if (G_UNLIKELY (ret != GST_FLOW_OK)) |
2866 goto error; |
3039 goto error; |
3040 |
|
2867 /* no error, but NULL buffer means fallback to the default */ |
3041 /* no error, but NULL buffer means fallback to the default */ |
2868 if (G_UNLIKELY (*buf == NULL)) |
3042 if (G_UNLIKELY (*buf == NULL)) |
2869 goto fallback; |
3043 goto fallback; |
2870 |
3044 |
2871 /* If the buffer alloc function didn't set up the caps like it should, |
3045 /* If the buffer alloc function didn't set up the caps like it should, |
2893 fallback: |
3067 fallback: |
2894 { |
3068 { |
2895 /* fallback case, allocate a buffer of our own, add pad caps. */ |
3069 /* fallback case, allocate a buffer of our own, add pad caps. */ |
2896 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "fallback buffer alloc"); |
3070 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "fallback buffer alloc"); |
2897 |
3071 |
2898 *buf = gst_buffer_new_and_alloc (size); |
3072 if ((*buf = gst_buffer_try_new_and_alloc (size))) { |
2899 GST_BUFFER_OFFSET (*buf) = offset; |
3073 GST_BUFFER_OFFSET (*buf) = offset; |
2900 gst_buffer_set_caps (*buf, caps); |
3074 gst_buffer_set_caps (*buf, caps); |
2901 |
3075 return GST_FLOW_OK; |
2902 return GST_FLOW_OK; |
3076 } else { |
2903 } |
3077 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, |
2904 } |
3078 "out of memory allocating %d bytes", size); |
2905 |
3079 return GST_FLOW_ERROR; |
3080 } |
|
3081 } |
|
3082 } |
|
3083 |
|
3084 /* FIXME 0.11: size should be unsigned */ |
|
2906 static GstFlowReturn |
3085 static GstFlowReturn |
2907 gst_pad_alloc_buffer_full (GstPad * pad, guint64 offset, gint size, |
3086 gst_pad_alloc_buffer_full (GstPad * pad, guint64 offset, gint size, |
2908 GstCaps * caps, GstBuffer ** buf, gboolean setcaps) |
3087 GstCaps * caps, GstBuffer ** buf, gboolean setcaps) |
2909 { |
3088 { |
2910 GstPad *peer; |
3089 GstPad *peer; |
2911 GstFlowReturn ret; |
3090 GstFlowReturn ret; |
3091 GstCaps *newcaps; |
|
2912 gboolean caps_changed; |
3092 gboolean caps_changed; |
2913 |
3093 |
2914 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
3094 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
2915 g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); |
3095 g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); |
2916 g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); |
3096 g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); |
2917 |
3097 g_return_val_if_fail (size >= 0, GST_FLOW_ERROR); |
2918 GST_DEBUG_OBJECT (pad, "offset %" G_GUINT64_FORMAT ", size %d", offset, size); |
3098 |
3099 GST_DEBUG_OBJECT (pad, "offset %" G_GUINT64_FORMAT ", size %d, caps %" |
|
3100 GST_PTR_FORMAT, offset, size, caps); |
|
2919 |
3101 |
2920 GST_OBJECT_LOCK (pad); |
3102 GST_OBJECT_LOCK (pad); |
2921 while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) |
3103 while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) |
2922 if ((ret = handle_pad_block (pad)) != GST_FLOW_OK) |
3104 if ((ret = handle_pad_block (pad)) != GST_FLOW_OK) |
2923 goto flushed; |
3105 goto flushed; |
2933 |
3115 |
2934 if (G_UNLIKELY (ret != GST_FLOW_OK)) |
3116 if (G_UNLIKELY (ret != GST_FLOW_OK)) |
2935 goto peer_error; |
3117 goto peer_error; |
2936 |
3118 |
2937 /* FIXME, move capnego this into a base class? */ |
3119 /* FIXME, move capnego this into a base class? */ |
2938 caps = GST_BUFFER_CAPS (*buf); |
3120 newcaps = GST_BUFFER_CAPS (*buf); |
2939 |
3121 |
2940 /* Lock for checking caps, pretty pointless as the _pad_push() function might |
3122 /* Lock for checking caps, pretty pointless as the _pad_push() function might |
2941 * change it concurrently, one of the problems with automatic caps setting in |
3123 * change it concurrently, one of the problems with automatic caps setting in |
2942 * pad_alloc_and_set_caps. Worst case, if does a check too much, but only |
3124 * pad_alloc_and_set_caps. Worst case, if does a check too much, but only |
2943 * when there is heavy renegotiation going on in both directions. */ |
3125 * when there is heavy renegotiation going on in both directions. */ |
2944 GST_OBJECT_LOCK (pad); |
3126 GST_OBJECT_LOCK (pad); |
2945 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
3127 caps_changed = newcaps && newcaps != GST_PAD_CAPS (pad); |
2946 GST_OBJECT_UNLOCK (pad); |
3128 GST_OBJECT_UNLOCK (pad); |
2947 |
3129 |
2948 /* we got a new datatype on the pad, see if it can handle it */ |
3130 /* we got a new datatype on the pad, see if it can handle it */ |
2949 if (G_UNLIKELY (caps_changed)) { |
3131 if (G_UNLIKELY (caps_changed)) { |
2950 GST_DEBUG_OBJECT (pad, |
3132 GST_DEBUG_OBJECT (pad, |
2951 "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT, |
3133 "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT, |
2952 GST_PAD_CAPS (pad), caps, caps); |
3134 GST_PAD_CAPS (pad), newcaps, newcaps); |
2953 if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, setcaps))) |
3135 if (G_UNLIKELY (!gst_pad_configure_src (pad, newcaps, setcaps))) |
2954 goto not_negotiated; |
3136 goto not_negotiated; |
2955 } |
3137 } |
3138 |
|
3139 /* sanity check (only if caps are the same) */ |
|
3140 if (G_LIKELY (newcaps == caps) && G_UNLIKELY (GST_BUFFER_SIZE (*buf) < size)) |
|
3141 goto wrong_size_fallback; |
|
3142 |
|
2956 return ret; |
3143 return ret; |
2957 |
3144 |
2958 flushed: |
3145 flushed: |
2959 { |
3146 { |
2960 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "pad block stopped by flush"); |
3147 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "pad block stopped by flush"); |
2980 gst_buffer_unref (*buf); |
3167 gst_buffer_unref (*buf); |
2981 *buf = NULL; |
3168 *buf = NULL; |
2982 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
3169 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
2983 "alloc function returned unacceptable buffer"); |
3170 "alloc function returned unacceptable buffer"); |
2984 return GST_FLOW_NOT_NEGOTIATED; |
3171 return GST_FLOW_NOT_NEGOTIATED; |
3172 } |
|
3173 wrong_size_fallback: |
|
3174 { |
|
3175 GST_CAT_ERROR_OBJECT (GST_CAT_PADS, pad, "buffer returned by alloc " |
|
3176 "function is too small (%u < %d), doing fallback buffer alloc", |
|
3177 GST_BUFFER_SIZE (*buf), size); |
|
3178 |
|
3179 gst_buffer_unref (*buf); |
|
3180 |
|
3181 if ((*buf = gst_buffer_try_new_and_alloc (size))) { |
|
3182 GST_BUFFER_OFFSET (*buf) = offset; |
|
3183 gst_buffer_set_caps (*buf, caps); |
|
3184 return GST_FLOW_OK; |
|
3185 } else { |
|
3186 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, |
|
3187 "out of memory allocating %d bytes", size); |
|
3188 return GST_FLOW_ERROR; |
|
3189 } |
|
2985 } |
3190 } |
2986 } |
3191 } |
2987 |
3192 |
2988 /** |
3193 /** |
2989 * gst_pad_alloc_buffer: |
3194 * gst_pad_alloc_buffer: |
2996 * Allocates a new, empty buffer optimized to push to pad @pad. This |
3201 * Allocates a new, empty buffer optimized to push to pad @pad. This |
2997 * function only works if @pad is a source pad and has a peer. |
3202 * function only works if @pad is a source pad and has a peer. |
2998 * |
3203 * |
2999 * A new, empty #GstBuffer will be put in the @buf argument. |
3204 * A new, empty #GstBuffer will be put in the @buf argument. |
3000 * You need to check the caps of the buffer after performing this |
3205 * You need to check the caps of the buffer after performing this |
3001 * function and renegotiate to the format if needed. |
3206 * function and renegotiate to the format if needed. If the caps changed, it is |
3207 * possible that the buffer returned in @buf is not of the right size for the |
|
3208 * new format, @buf needs to be unreffed and reallocated if this is the case. |
|
3002 * |
3209 * |
3003 * Returns: a result code indicating success of the operation. Any |
3210 * Returns: a result code indicating success of the operation. Any |
3004 * result code other than #GST_FLOW_OK is an error and @buf should |
3211 * result code other than #GST_FLOW_OK is an error and @buf should |
3005 * not be used. |
3212 * not be used. |
3006 * An error can occur if the pad is not connected or when the downstream |
3213 * An error can occur if the pad is not connected or when the downstream |
3007 * peer elements cannot provide an acceptable buffer. |
3214 * peer elements cannot provide an acceptable buffer. |
3008 * |
3215 * |
3009 * MT safe. |
3216 * MT safe. |
3010 */ |
3217 */ |
3218 |
|
3219 /* FIXME 0.11: size should be unsigned */ |
|
3011 #ifdef __SYMBIAN32__ |
3220 #ifdef __SYMBIAN32__ |
3012 EXPORT_C |
3221 EXPORT_C |
3013 #endif |
3222 #endif |
3014 |
3223 |
3015 GstFlowReturn |
3224 GstFlowReturn |
3029 * |
3238 * |
3030 * In addition to the function gst_pad_alloc_buffer(), this function |
3239 * In addition to the function gst_pad_alloc_buffer(), this function |
3031 * automatically calls gst_pad_set_caps() when the caps of the |
3240 * automatically calls gst_pad_set_caps() when the caps of the |
3032 * newly allocated buffer are different from the @pad caps. |
3241 * newly allocated buffer are different from the @pad caps. |
3033 * |
3242 * |
3243 * After a renegotiation, the size of the new buffer returned in @buf could |
|
3244 * be of the wrong size for the new format and must be unreffed an reallocated |
|
3245 * in that case. |
|
3246 * |
|
3034 * Returns: a result code indicating success of the operation. Any |
3247 * Returns: a result code indicating success of the operation. Any |
3035 * result code other than #GST_FLOW_OK is an error and @buf should |
3248 * result code other than #GST_FLOW_OK is an error and @buf should |
3036 * not be used. |
3249 * not be used. |
3037 * An error can occur if the pad is not connected or when the downstream |
3250 * An error can occur if the pad is not connected or when the downstream |
3038 * peer elements cannot provide an acceptable buffer. |
3251 * peer elements cannot provide an acceptable buffer. |
3039 * |
3252 * |
3040 * MT safe. |
3253 * MT safe. |
3041 */ |
3254 */ |
3255 |
|
3256 /* FIXME 0.11: size should be unsigned */ |
|
3042 #ifdef __SYMBIAN32__ |
3257 #ifdef __SYMBIAN32__ |
3043 EXPORT_C |
3258 EXPORT_C |
3044 #endif |
3259 #endif |
3045 |
3260 |
3046 GstFlowReturn |
3261 GstFlowReturn |
3047 gst_pad_alloc_buffer_and_set_caps (GstPad * pad, guint64 offset, gint size, |
3262 gst_pad_alloc_buffer_and_set_caps (GstPad * pad, guint64 offset, gint size, |
3048 GstCaps * caps, GstBuffer ** buf) |
3263 GstCaps * caps, GstBuffer ** buf) |
3049 { |
3264 { |
3050 return gst_pad_alloc_buffer_full (pad, offset, size, caps, buf, TRUE); |
3265 return gst_pad_alloc_buffer_full (pad, offset, size, caps, buf, TRUE); |
3051 } |
3266 } |
3267 |
|
3268 |
|
3269 #ifndef GST_REMOVE_DEPRECATED |
|
3270 typedef struct |
|
3271 { |
|
3272 GList *list; |
|
3273 guint32 cookie; |
|
3274 } IntLinkIterData; |
|
3275 |
|
3276 static void |
|
3277 int_link_iter_data_free (IntLinkIterData * data) |
|
3278 { |
|
3279 g_list_free (data->list); |
|
3280 g_free (data); |
|
3281 } |
|
3282 #endif |
|
3283 |
|
3284 static GstIteratorItem |
|
3285 iterate_pad (GstIterator * it, GstPad * pad) |
|
3286 { |
|
3287 gst_object_ref (pad); |
|
3288 return GST_ITERATOR_ITEM_PASS; |
|
3289 } |
|
3290 |
|
3291 /** |
|
3292 * gst_pad_iterate_internal_links_default: |
|
3293 * @pad: the #GstPad to get the internal links of. |
|
3294 * |
|
3295 * Iterate the list of pads to which the given pad is linked to inside of |
|
3296 * the parent element. |
|
3297 * This is the default handler, and thus returns an iterator of all of the |
|
3298 * pads inside the parent element with opposite direction. |
|
3299 * |
|
3300 * The caller must free this iterator after use with gst_iterator_free(). |
|
3301 * |
|
3302 * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each |
|
3303 * returned pad with gst_object_unref(). |
|
3304 * |
|
3305 * Since: 0.10.21 |
|
3306 */ |
|
3307 #ifdef __SYMBIAN32__ |
|
3308 EXPORT_C |
|
3309 #endif |
|
3310 |
|
3311 GstIterator * |
|
3312 gst_pad_iterate_internal_links_default (GstPad * pad) |
|
3313 { |
|
3314 GstIterator *res; |
|
3315 GList **padlist; |
|
3316 guint32 *cookie; |
|
3317 GMutex *lock; |
|
3318 gpointer owner; |
|
3319 GstIteratorDisposeFunction dispose; |
|
3320 |
|
3321 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
3322 |
|
3323 #ifndef GST_REMOVE_DEPRECATED |
|
3324 /* when we get here, the default handler for the iterate links is called, |
|
3325 * which means that the user has not installed a custom one. We first check if |
|
3326 * there is maybe a custom legacy function we can call. */ |
|
3327 if (GST_PAD_INTLINKFUNC (pad) && |
|
3328 GST_PAD_INTLINKFUNC (pad) != gst_pad_get_internal_links_default) { |
|
3329 IntLinkIterData *data; |
|
3330 |
|
3331 /* make an iterator for the list. We can't protect the list with a |
|
3332 * cookie. If we would take the cookie of the parent element, we need to |
|
3333 * have a parent, which is not required for GST_PAD_INTLINKFUNC(). We could |
|
3334 * cache the per-pad list and invalidate the list when a new call to |
|
3335 * INTLINKFUNC() returned a different list but then this would only work if |
|
3336 * two concurrent iterators were used and the last iterator would still be |
|
3337 * thread-unsafe. Just don't use this method anymore. */ |
|
3338 data = g_new0 (IntLinkIterData, 1); |
|
3339 data->list = GST_PAD_INTLINKFUNC (pad) (pad); |
|
3340 data->cookie = 0; |
|
3341 |
|
3342 GST_WARNING_OBJECT (pad, "Making unsafe iterator"); |
|
3343 |
|
3344 cookie = &data->cookie; |
|
3345 padlist = &data->list; |
|
3346 owner = data; |
|
3347 dispose = (GstIteratorDisposeFunction) int_link_iter_data_free; |
|
3348 /* reuse the pad lock, it's all we have here */ |
|
3349 lock = GST_OBJECT_GET_LOCK (pad); |
|
3350 } else |
|
3351 #endif |
|
3352 { |
|
3353 GstElement *parent; |
|
3354 |
|
3355 GST_OBJECT_LOCK (pad); |
|
3356 parent = GST_PAD_PARENT (pad); |
|
3357 if (!parent || !GST_IS_ELEMENT (parent)) |
|
3358 goto no_parent; |
|
3359 |
|
3360 gst_object_ref (parent); |
|
3361 GST_OBJECT_UNLOCK (pad); |
|
3362 |
|
3363 if (pad->direction == GST_PAD_SRC) |
|
3364 padlist = &parent->sinkpads; |
|
3365 else |
|
3366 padlist = &parent->srcpads; |
|
3367 |
|
3368 GST_DEBUG_OBJECT (pad, "Making iterator"); |
|
3369 |
|
3370 cookie = &parent->pads_cookie; |
|
3371 owner = parent; |
|
3372 dispose = (GstIteratorDisposeFunction) gst_object_unref; |
|
3373 lock = GST_OBJECT_GET_LOCK (parent); |
|
3374 } |
|
3375 |
|
3376 res = gst_iterator_new_list (GST_TYPE_PAD, |
|
3377 lock, cookie, padlist, owner, (GstIteratorItemFunction) iterate_pad, |
|
3378 dispose); |
|
3379 |
|
3380 return res; |
|
3381 |
|
3382 /* ERRORS */ |
|
3383 no_parent: |
|
3384 { |
|
3385 GST_OBJECT_UNLOCK (pad); |
|
3386 GST_DEBUG_OBJECT (pad, "no parent element"); |
|
3387 return NULL; |
|
3388 } |
|
3389 } |
|
3390 |
|
3391 /** |
|
3392 * gst_pad_iterate_internal_links: |
|
3393 * @pad: the GstPad to get the internal links of. |
|
3394 * |
|
3395 * Gets an iterator for the pads to which the given pad is linked to inside |
|
3396 * of the parent element. |
|
3397 * |
|
3398 * Each #GstPad element yielded by the iterator will have its refcount increased, |
|
3399 * so unref after use. |
|
3400 * |
|
3401 * Returns: a new #GstIterator of #GstPad or %NULL when the pad does not have an |
|
3402 * iterator function configured. Use gst_iterator_free() after usage. |
|
3403 * |
|
3404 * Since: 0.10.21 |
|
3405 */ |
|
3406 #ifdef __SYMBIAN32__ |
|
3407 EXPORT_C |
|
3408 #endif |
|
3409 |
|
3410 GstIterator * |
|
3411 gst_pad_iterate_internal_links (GstPad * pad) |
|
3412 { |
|
3413 GstIterator *res = NULL; |
|
3414 |
|
3415 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
3416 |
|
3417 if (GST_PAD_ITERINTLINKFUNC (pad)) |
|
3418 res = GST_PAD_ITERINTLINKFUNC (pad) (pad); |
|
3419 |
|
3420 return res; |
|
3421 } |
|
3422 |
|
3423 #ifndef GST_REMOVE_DEPRECATED |
|
3424 static void |
|
3425 add_unref_pad_to_list (GstPad * pad, GList * list) |
|
3426 { |
|
3427 list = g_list_prepend (list, pad); |
|
3428 gst_object_unref (pad); |
|
3429 } |
|
3430 #endif |
|
3052 |
3431 |
3053 /** |
3432 /** |
3054 * gst_pad_get_internal_links_default: |
3433 * gst_pad_get_internal_links_default: |
3055 * @pad: the #GstPad to get the internal links of. |
3434 * @pad: the #GstPad to get the internal links of. |
3056 * |
3435 * |
3057 * Gets a list of pads to which the given pad is linked to |
3436 * Gets a list of pads to which the given pad is linked to |
3058 * inside of the parent element. |
3437 * inside of the parent element. |
3059 * This is the default handler, and thus returns a list of all of the |
3438 * This is the default handler, and thus returns a list of all of the |
3060 * pads inside the parent element with opposite direction. |
3439 * pads inside the parent element with opposite direction. |
3061 * The caller must free this list after use. |
3440 * |
3441 * The caller must free this list after use with g_list_free(). |
|
3062 * |
3442 * |
3063 * Returns: a newly allocated #GList of pads, or NULL if the pad has no parent. |
3443 * Returns: a newly allocated #GList of pads, or NULL if the pad has no parent. |
3064 * |
3444 * |
3065 * Not MT safe. |
3445 * Not MT safe. |
3066 */ |
3446 * |
3067 #ifdef __SYMBIAN32__ |
3447 * Deprecated: This function does not ref the pads in the list so that they |
3068 EXPORT_C |
3448 * could become invalid by the time the application accesses them. It's also |
3069 #endif |
3449 * possible that the list changes while handling the pads, which the caller of |
3070 |
3450 * this function is unable to know. Use the thread-safe |
3451 * gst_pad_iterate_internal_links_default() instead. |
|
3452 */ |
|
3453 #ifndef GST_REMOVE_DEPRECATED |
|
3454 #ifdef __SYMBIAN32__ |
|
3455 EXPORT_C |
|
3456 #endif |
|
3071 GList * |
3457 GList * |
3072 gst_pad_get_internal_links_default (GstPad * pad) |
3458 gst_pad_get_internal_links_default (GstPad * pad) |
3073 { |
3459 { |
3074 GList *res = NULL; |
3460 GList *res = NULL; |
3075 GstElement *parent; |
3461 GstElement *parent; |
3076 GList *parent_pads; |
|
3077 GstPadDirection direction; |
|
3078 |
3462 |
3079 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
3463 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
3080 |
3464 |
3081 direction = pad->direction; |
3465 GST_WARNING_OBJECT (pad, "Unsafe internal links used"); |
3082 |
3466 |
3083 parent = GST_PAD_PARENT (pad); |
3467 /* when we get here, the default handler for get_internal_links is called, |
3084 if (!parent) |
3468 * which means that the user has not installed a custom one. We first check if |
3085 goto no_parent; |
3469 * there is maybe a custom iterate function we can call. */ |
3086 |
3470 if (GST_PAD_ITERINTLINKFUNC (pad) && |
3087 parent_pads = parent->pads; |
3471 GST_PAD_ITERINTLINKFUNC (pad) != gst_pad_iterate_internal_links_default) { |
3088 |
3472 GstIterator *it; |
3089 while (parent_pads) { |
3473 GstIteratorResult ires; |
3090 GstPad *parent_pad = GST_PAD_CAST (parent_pads->data); |
3474 gboolean done = FALSE; |
3091 |
3475 |
3092 if (parent_pad->direction != direction) { |
3476 it = gst_pad_iterate_internal_links (pad); |
3093 GST_DEBUG_OBJECT (pad, "adding pad %s:%s", |
3477 /* loop over the iterator and put all elements into a list, we also |
3094 GST_DEBUG_PAD_NAME (parent_pad)); |
3478 * immediatly unref them, which is bad. */ |
3095 res = g_list_prepend (res, parent_pad); |
3479 do { |
3096 } |
3480 ires = gst_iterator_foreach (it, (GFunc) add_unref_pad_to_list, res); |
3097 parent_pads = g_list_next (parent_pads); |
3481 switch (ires) { |
3098 } |
3482 case GST_ITERATOR_OK: |
3483 case GST_ITERATOR_DONE: |
|
3484 case GST_ITERATOR_ERROR: |
|
3485 done = TRUE; |
|
3486 break; |
|
3487 case GST_ITERATOR_RESYNC: |
|
3488 /* restart, discard previous list */ |
|
3489 gst_iterator_resync (it); |
|
3490 g_list_free (res); |
|
3491 res = NULL; |
|
3492 break; |
|
3493 } |
|
3494 } while (!done); |
|
3495 |
|
3496 gst_iterator_free (it); |
|
3497 } else { |
|
3498 /* lock pad, check and ref parent */ |
|
3499 GST_OBJECT_LOCK (pad); |
|
3500 parent = GST_PAD_PARENT (pad); |
|
3501 if (!parent || !GST_IS_ELEMENT (parent)) |
|
3502 goto no_parent; |
|
3503 |
|
3504 parent = gst_object_ref (parent); |
|
3505 GST_OBJECT_UNLOCK (pad); |
|
3506 |
|
3507 /* now lock the parent while we copy the pads */ |
|
3508 GST_OBJECT_LOCK (parent); |
|
3509 if (pad->direction == GST_PAD_SRC) |
|
3510 res = g_list_copy (parent->sinkpads); |
|
3511 else |
|
3512 res = g_list_copy (parent->srcpads); |
|
3513 GST_OBJECT_UNLOCK (parent); |
|
3514 |
|
3515 gst_object_unref (parent); |
|
3516 } |
|
3517 |
|
3518 /* At this point pads can be changed and unreffed. Nothing we can do about it |
|
3519 * because for compatibility reasons this function cannot ref the pads or |
|
3520 * notify the app that the list changed. */ |
|
3521 |
|
3099 return res; |
3522 return res; |
3100 |
3523 |
3101 no_parent: |
3524 no_parent: |
3102 { |
3525 { |
3103 GST_DEBUG_OBJECT (pad, "no parent"); |
3526 GST_DEBUG_OBJECT (pad, "no parent"); |
3527 GST_OBJECT_UNLOCK (pad); |
|
3104 return NULL; |
3528 return NULL; |
3105 } |
3529 } |
3106 } |
3530 } |
3531 #endif /* GST_REMOVE_DEPRECATED */ |
|
3107 |
3532 |
3108 /** |
3533 /** |
3109 * gst_pad_get_internal_links: |
3534 * gst_pad_get_internal_links: |
3110 * @pad: the #GstPad to get the internal links of. |
3535 * @pad: the #GstPad to get the internal links of. |
3111 * |
3536 * |
3112 * Gets a list of pads to which the given pad is linked to |
3537 * Gets a list of pads to which the given pad is linked to |
3113 * inside of the parent element. |
3538 * inside of the parent element. |
3114 * The caller must free this list after use. |
3539 * The caller must free this list after use. |
3115 * |
3540 * |
3116 * Returns: a newly allocated #GList of pads. |
|
3117 * |
|
3118 * Not MT safe. |
3541 * Not MT safe. |
3119 */ |
3542 * |
3120 #ifdef __SYMBIAN32__ |
3543 * Returns: a newly allocated #GList of pads, free with g_list_free(). |
3121 EXPORT_C |
3544 * |
3122 #endif |
3545 * Deprecated: This function does not ref the pads in the list so that they |
3123 |
3546 * could become invalid by the time the application accesses them. It's also |
3547 * possible that the list changes while handling the pads, which the caller of |
|
3548 * this function is unable to know. Use the thread-safe |
|
3549 * gst_pad_iterate_internal_links() instead. |
|
3550 */ |
|
3551 #ifndef GST_REMOVE_DEPRECATED |
|
3552 #ifdef __SYMBIAN32__ |
|
3553 EXPORT_C |
|
3554 #endif |
|
3124 GList * |
3555 GList * |
3125 gst_pad_get_internal_links (GstPad * pad) |
3556 gst_pad_get_internal_links (GstPad * pad) |
3126 { |
3557 { |
3127 GList *res = NULL; |
3558 GList *res = NULL; |
3128 |
3559 |
3129 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
3560 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
3130 |
3561 |
3562 GST_WARNING_OBJECT (pad, "Calling unsafe internal links"); |
|
3563 |
|
3131 if (GST_PAD_INTLINKFUNC (pad)) |
3564 if (GST_PAD_INTLINKFUNC (pad)) |
3132 res = GST_PAD_INTLINKFUNC (pad) (pad); |
3565 res = GST_PAD_INTLINKFUNC (pad) (pad); |
3133 |
3566 |
3134 return res; |
3567 return res; |
3135 } |
3568 } |
3136 |
3569 #endif /* GST_REMOVE_DEPRECATED */ |
3137 |
3570 |
3138 static gboolean |
3571 static gboolean |
3139 gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event) |
3572 gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event) |
3140 { |
3573 { |
3141 GList *orig, *pads; |
3574 gboolean result = FALSE; |
3142 gboolean result; |
3575 GstIterator *iter; |
3576 gboolean done = FALSE; |
|
3577 gpointer item; |
|
3578 GstPad *eventpad; |
|
3579 GList *pushed_pads = NULL; |
|
3143 |
3580 |
3144 GST_INFO_OBJECT (pad, "Sending event %p (%s) to all internally linked pads", |
3581 GST_INFO_OBJECT (pad, "Sending event %p (%s) to all internally linked pads", |
3145 event, GST_EVENT_TYPE_NAME (event)); |
3582 event, GST_EVENT_TYPE_NAME (event)); |
3146 |
3583 |
3147 result = (GST_PAD_DIRECTION (pad) == GST_PAD_SINK); |
3584 iter = gst_pad_iterate_internal_links (pad); |
3148 |
3585 |
3149 orig = pads = gst_pad_get_internal_links (pad); |
3586 if (!iter) |
3150 |
3587 goto no_iter; |
3151 while (pads) { |
3588 |
3152 GstPad *eventpad = GST_PAD_CAST (pads->data); |
3589 while (!done) { |
3153 |
3590 switch (gst_iterator_next (iter, &item)) { |
3154 pads = g_list_next (pads); |
3591 case GST_ITERATOR_OK: |
3155 |
3592 eventpad = GST_PAD (item); |
3156 if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) { |
3593 |
3157 /* for each pad we send to, we should ref the event; it's up |
3594 /* if already pushed, skip */ |
3158 * to downstream to unref again when handled. */ |
3595 if (g_list_find (pushed_pads, eventpad)) { |
3159 GST_LOG_OBJECT (pad, "Reffing and sending event %p (%s) to %s:%s", |
3596 gst_object_unref (item); |
3160 event, GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (eventpad)); |
3597 break; |
3161 gst_event_ref (event); |
3598 } |
3162 gst_pad_push_event (eventpad, event); |
3599 |
3163 } else { |
3600 if (GST_PAD_IS_SRC (eventpad)) { |
3164 /* we only send the event on one pad, multi-sinkpad elements |
3601 /* for each pad we send to, we should ref the event; it's up |
3165 * should implement a handler */ |
3602 * to downstream to unref again when handled. */ |
3166 GST_LOG_OBJECT (pad, "sending event %p (%s) to one sink pad %s:%s", |
3603 GST_LOG_OBJECT (pad, "Reffing and sending event %p (%s) to %s:%s", |
3167 event, GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (eventpad)); |
3604 event, GST_EVENT_TYPE_NAME (event), |
3168 result = gst_pad_push_event (eventpad, event); |
3605 GST_DEBUG_PAD_NAME (eventpad)); |
3169 goto done; |
3606 gst_event_ref (event); |
3607 result |= gst_pad_push_event (eventpad, event); |
|
3608 } else { |
|
3609 /* we only send the event on one pad, multi-sinkpad elements |
|
3610 * should implement a handler */ |
|
3611 GST_LOG_OBJECT (pad, "sending event %p (%s) to one sink pad %s:%s", |
|
3612 event, GST_EVENT_TYPE_NAME (event), |
|
3613 GST_DEBUG_PAD_NAME (eventpad)); |
|
3614 result = gst_pad_push_event (eventpad, event); |
|
3615 done = TRUE; |
|
3616 event = NULL; |
|
3617 } |
|
3618 |
|
3619 pushed_pads = g_list_prepend (pushed_pads, eventpad); |
|
3620 |
|
3621 gst_object_unref (item); |
|
3622 break; |
|
3623 case GST_ITERATOR_RESYNC: |
|
3624 /* FIXME, if we want to reset the result value we need to remember which |
|
3625 * pads pushed with which result */ |
|
3626 gst_iterator_resync (iter); |
|
3627 break; |
|
3628 case GST_ITERATOR_ERROR: |
|
3629 GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads"); |
|
3630 done = TRUE; |
|
3631 break; |
|
3632 case GST_ITERATOR_DONE: |
|
3633 done = TRUE; |
|
3634 break; |
|
3170 } |
3635 } |
3171 } |
3636 } |
3637 gst_iterator_free (iter); |
|
3638 |
|
3639 no_iter: |
|
3640 |
|
3641 /* If this is a sinkpad and we don't have pads to send the event to, we |
|
3642 * return TRUE. This is so that when using the default handler on a sink |
|
3643 * element, we don't fail to push it. */ |
|
3644 if (!pushed_pads) |
|
3645 result = GST_PAD_IS_SINK (pad); |
|
3646 |
|
3647 g_list_free (pushed_pads); |
|
3648 |
|
3172 /* we handled the incoming event so we unref once */ |
3649 /* we handled the incoming event so we unref once */ |
3173 GST_LOG_OBJECT (pad, "handled event %p, unreffing", event); |
3650 if (event) { |
3174 gst_event_unref (event); |
3651 GST_LOG_OBJECT (pad, "handled event %p, unreffing", event); |
3175 |
3652 gst_event_unref (event); |
3176 done: |
3653 } |
3177 g_list_free (orig); |
|
3178 |
3654 |
3179 return result; |
3655 return result; |
3180 } |
3656 } |
3181 |
3657 |
3182 /** |
3658 /** |
3199 gboolean |
3675 gboolean |
3200 gst_pad_event_default (GstPad * pad, GstEvent * event) |
3676 gst_pad_event_default (GstPad * pad, GstEvent * event) |
3201 { |
3677 { |
3202 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
3678 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
3203 g_return_val_if_fail (event != NULL, FALSE); |
3679 g_return_val_if_fail (event != NULL, FALSE); |
3680 |
|
3681 GST_LOG_OBJECT (pad, "default event handler"); |
|
3204 |
3682 |
3205 switch (GST_EVENT_TYPE (event)) { |
3683 switch (GST_EVENT_TYPE (event)) { |
3206 case GST_EVENT_EOS: |
3684 case GST_EVENT_EOS: |
3207 { |
3685 { |
3208 GST_DEBUG_OBJECT (pad, "pausing task because of eos"); |
3686 GST_DEBUG_OBJECT (pad, "pausing task because of eos"); |
3236 gboolean |
3714 gboolean |
3237 gst_pad_dispatcher (GstPad * pad, GstPadDispatcherFunction dispatch, |
3715 gst_pad_dispatcher (GstPad * pad, GstPadDispatcherFunction dispatch, |
3238 gpointer data) |
3716 gpointer data) |
3239 { |
3717 { |
3240 gboolean res = FALSE; |
3718 gboolean res = FALSE; |
3241 GList *int_pads, *orig; |
3719 GstIterator *iter = NULL; |
3720 gboolean done = FALSE; |
|
3721 gpointer item; |
|
3242 |
3722 |
3243 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
3723 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
3244 g_return_val_if_fail (dispatch != NULL, FALSE); |
3724 g_return_val_if_fail (dispatch != NULL, FALSE); |
3245 |
3725 |
3246 orig = int_pads = gst_pad_get_internal_links (pad); |
3726 iter = gst_pad_iterate_internal_links (pad); |
3247 |
3727 |
3248 while (int_pads) { |
3728 if (!iter) |
3249 GstPad *int_pad = GST_PAD_CAST (int_pads->data); |
3729 goto no_iter; |
3250 GstPad *int_peer = gst_pad_get_peer (int_pad); |
3730 |
3251 |
3731 while (!done) { |
3252 if (int_peer) { |
3732 switch (gst_iterator_next (iter, &item)) { |
3253 GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s", |
3733 case GST_ITERATOR_OK: |
3254 GST_DEBUG_PAD_NAME (int_peer)); |
3734 { |
3255 res = dispatch (int_peer, data); |
3735 GstPad *int_pad = GST_PAD_CAST (item); |
3256 gst_object_unref (int_peer); |
3736 GstPad *int_peer = gst_pad_get_peer (int_pad); |
3257 if (res) |
3737 |
3738 if (int_peer) { |
|
3739 GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s", |
|
3740 GST_DEBUG_PAD_NAME (int_peer)); |
|
3741 done = res = dispatch (int_peer, data); |
|
3742 gst_object_unref (int_peer); |
|
3743 } else { |
|
3744 GST_DEBUG_OBJECT (int_pad, "no peer"); |
|
3745 } |
|
3746 } |
|
3747 gst_object_unref (item); |
|
3258 break; |
3748 break; |
3259 } else { |
3749 case GST_ITERATOR_RESYNC: |
3260 GST_DEBUG_OBJECT (int_pad, "no peer"); |
3750 gst_iterator_resync (iter); |
3751 break; |
|
3752 case GST_ITERATOR_ERROR: |
|
3753 done = TRUE; |
|
3754 GST_ERROR_OBJECT (pad, "Could not iterate internally linked pads"); |
|
3755 break; |
|
3756 case GST_ITERATOR_DONE: |
|
3757 done = TRUE; |
|
3758 break; |
|
3261 } |
3759 } |
3262 int_pads = g_list_next (int_pads); |
3760 } |
3263 } |
3761 gst_iterator_free (iter); |
3264 g_list_free (orig); |
3762 |
3265 GST_DEBUG_OBJECT (pad, "done, result %d", res); |
3763 GST_DEBUG_OBJECT (pad, "done, result %d", res); |
3764 |
|
3765 no_iter: |
|
3266 |
3766 |
3267 return res; |
3767 return res; |
3268 } |
3768 } |
3269 |
3769 |
3270 /** |
3770 /** |
3409 void |
3909 void |
3410 gst_pad_load_and_link (xmlNodePtr self, GstObject * parent) |
3910 gst_pad_load_and_link (xmlNodePtr self, GstObject * parent) |
3411 { |
3911 { |
3412 xmlNodePtr field = self->xmlChildrenNode; |
3912 xmlNodePtr field = self->xmlChildrenNode; |
3413 GstPad *pad = NULL, *targetpad; |
3913 GstPad *pad = NULL, *targetpad; |
3914 GstPadTemplate *tmpl; |
|
3414 gchar *peer = NULL; |
3915 gchar *peer = NULL; |
3415 gchar **split; |
3916 gchar **split; |
3416 GstElement *target; |
3917 GstElement *target; |
3417 GstObject *grandparent; |
3918 GstObject *grandparent; |
3418 gchar *name = NULL; |
3919 gchar *name = NULL; |
3419 |
3920 |
3420 while (field) { |
3921 while (field) { |
3421 if (!strcmp ((char *) field->name, "name")) { |
3922 if (!strcmp ((char *) field->name, "name")) { |
3422 name = (gchar *) xmlNodeGetContent (field); |
3923 name = (gchar *) xmlNodeGetContent (field); |
3423 pad = gst_element_get_pad (GST_ELEMENT (parent), name); |
3924 pad = gst_element_get_static_pad (GST_ELEMENT (parent), name); |
3925 if ((!pad) || ((tmpl = gst_pad_get_pad_template (pad)) |
|
3926 && (GST_PAD_REQUEST == GST_PAD_TEMPLATE_PRESENCE (tmpl)))) |
|
3927 pad = gst_element_get_request_pad (GST_ELEMENT (parent), name); |
|
3424 g_free (name); |
3928 g_free (name); |
3425 } else if (!strcmp ((char *) field->name, "peer")) { |
3929 } else if (!strcmp ((char *) field->name, "peer")) { |
3426 peer = (gchar *) xmlNodeGetContent (field); |
3930 peer = (gchar *) xmlNodeGetContent (field); |
3427 } |
3931 } |
3428 field = field->next; |
3932 field = field->next; |
3454 goto cleanup; |
3958 goto cleanup; |
3455 |
3959 |
3456 if (target == NULL) |
3960 if (target == NULL) |
3457 goto cleanup; |
3961 goto cleanup; |
3458 |
3962 |
3459 targetpad = gst_element_get_pad (target, split[1]); |
3963 targetpad = gst_element_get_static_pad (target, split[1]); |
3964 if (!pad) |
|
3965 targetpad = gst_element_get_request_pad (target, split[1]); |
|
3460 |
3966 |
3461 if (targetpad == NULL) |
3967 if (targetpad == NULL) |
3462 goto cleanup; |
3968 goto cleanup; |
3463 |
3969 |
3464 gst_pad_link (pad, targetpad); |
3970 if (gst_pad_get_direction (pad) == GST_PAD_SRC) |
3971 gst_pad_link (pad, targetpad); |
|
3972 else |
|
3973 gst_pad_link (targetpad, pad); |
|
3465 |
3974 |
3466 cleanup: |
3975 cleanup: |
3467 g_strfreev (split); |
3976 g_strfreev (split); |
3468 } |
3977 } |
3469 |
3978 |
3591 * the callback, which is in the end totally impossible as it |
4100 * the callback, which is in the end totally impossible as it |
3592 * requires grabbing the STREAM_LOCK and OBJECT_LOCK which are |
4101 * requires grabbing the STREAM_LOCK and OBJECT_LOCK which are |
3593 * all taken when calling this function. */ |
4102 * all taken when calling this function. */ |
3594 gst_object_ref (pad); |
4103 gst_object_ref (pad); |
3595 |
4104 |
3596 /* we either have a callback installed to notify the block or |
|
3597 * some other thread is doing a GCond wait. */ |
|
3598 callback = pad->block_callback; |
|
3599 if (callback) { |
|
3600 /* there is a callback installed, call it. We release the |
|
3601 * lock so that the callback can do something usefull with the |
|
3602 * pad */ |
|
3603 user_data = pad->block_data; |
|
3604 GST_OBJECT_UNLOCK (pad); |
|
3605 callback (pad, TRUE, user_data); |
|
3606 GST_OBJECT_LOCK (pad); |
|
3607 |
|
3608 /* we released the lock, recheck flushing */ |
|
3609 if (GST_PAD_IS_FLUSHING (pad)) |
|
3610 goto flushing; |
|
3611 } else { |
|
3612 /* no callback, signal the thread that is doing a GCond wait |
|
3613 * if any. */ |
|
3614 GST_PAD_BLOCK_BROADCAST (pad); |
|
3615 } |
|
3616 |
|
3617 /* OBJECT_LOCK could have been released when we did the callback, which |
|
3618 * then could have made the pad unblock so we need to check the blocking |
|
3619 * condition again. */ |
|
3620 while (GST_PAD_IS_BLOCKED (pad)) { |
4105 while (GST_PAD_IS_BLOCKED (pad)) { |
4106 do { |
|
4107 /* we either have a callback installed to notify the block or |
|
4108 * some other thread is doing a GCond wait. */ |
|
4109 callback = pad->block_callback; |
|
4110 pad->abidata.ABI.block_callback_called = TRUE; |
|
4111 if (callback) { |
|
4112 /* there is a callback installed, call it. We release the |
|
4113 * lock so that the callback can do something usefull with the |
|
4114 * pad */ |
|
4115 user_data = pad->block_data; |
|
4116 GST_OBJECT_UNLOCK (pad); |
|
4117 callback (pad, TRUE, user_data); |
|
4118 GST_OBJECT_LOCK (pad); |
|
4119 |
|
4120 /* we released the lock, recheck flushing */ |
|
4121 if (GST_PAD_IS_FLUSHING (pad)) |
|
4122 goto flushing; |
|
4123 } else { |
|
4124 /* no callback, signal the thread that is doing a GCond wait |
|
4125 * if any. */ |
|
4126 GST_PAD_BLOCK_BROADCAST (pad); |
|
4127 } |
|
4128 } while (pad->abidata.ABI.block_callback_called == FALSE |
|
4129 && GST_PAD_IS_BLOCKED (pad)); |
|
4130 |
|
4131 /* OBJECT_LOCK could have been released when we did the callback, which |
|
4132 * then could have made the pad unblock so we need to check the blocking |
|
4133 * condition again. */ |
|
4134 if (!GST_PAD_IS_BLOCKED (pad)) |
|
4135 break; |
|
4136 |
|
3621 /* now we block the streaming thread. It can be unlocked when we |
4137 /* now we block the streaming thread. It can be unlocked when we |
3622 * deactivate the pad (which will also set the FLUSHING flag) or |
4138 * deactivate the pad (which will also set the FLUSHING flag) or |
3623 * when the pad is unblocked. A flushing event will also unblock |
4139 * when the pad is unblocked. A flushing event will also unblock |
3624 * the pad after setting the FLUSHING flag. */ |
4140 * the pad after setting the FLUSHING flag. */ |
3625 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
4141 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
3701 g_value_unset (&args[1]); |
4217 g_value_unset (&args[1]); |
3702 |
4218 |
3703 return res; |
4219 return res; |
3704 } |
4220 } |
3705 |
4221 |
4222 static void |
|
4223 gst_pad_data_unref (gboolean is_buffer, void *data) |
|
4224 { |
|
4225 if (G_LIKELY (is_buffer)) { |
|
4226 gst_buffer_unref (data); |
|
4227 } else { |
|
4228 gst_buffer_list_unref (data); |
|
4229 } |
|
4230 } |
|
4231 |
|
4232 static GstCaps * |
|
4233 gst_pad_data_get_caps (gboolean is_buffer, void *data) |
|
4234 { |
|
4235 GstCaps *caps; |
|
4236 |
|
4237 if (G_LIKELY (is_buffer)) { |
|
4238 caps = GST_BUFFER_CAPS (data); |
|
4239 } else { |
|
4240 GstBuffer *buf; |
|
4241 |
|
4242 if ((buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (data), 0, 0))) |
|
4243 caps = GST_BUFFER_CAPS (buf); |
|
4244 else |
|
4245 caps = NULL; |
|
4246 } |
|
4247 return caps; |
|
4248 } |
|
4249 |
|
3706 /* this is the chain function that does not perform the additional argument |
4250 /* this is the chain function that does not perform the additional argument |
3707 * checking for that little extra speed. |
4251 * checking for that little extra speed. |
3708 */ |
4252 */ |
3709 static inline GstFlowReturn |
4253 static inline GstFlowReturn |
3710 gst_pad_chain_unchecked (GstPad * pad, GstBuffer * buffer) |
4254 gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data) |
3711 { |
4255 { |
3712 GstCaps *caps; |
4256 GstCaps *caps; |
3713 gboolean caps_changed; |
4257 gboolean caps_changed; |
3714 GstPadChainFunction chainfunc; |
|
3715 GstFlowReturn ret; |
4258 GstFlowReturn ret; |
3716 gboolean emit_signal; |
4259 gboolean emit_signal; |
3717 |
4260 |
3718 GST_PAD_STREAM_LOCK (pad); |
4261 GST_PAD_STREAM_LOCK (pad); |
3719 |
4262 |
3720 GST_OBJECT_LOCK (pad); |
4263 GST_OBJECT_LOCK (pad); |
3721 if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) |
4264 if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) |
3722 goto flushing; |
4265 goto flushing; |
3723 |
4266 |
3724 caps = GST_BUFFER_CAPS (buffer); |
4267 caps = gst_pad_data_get_caps (is_buffer, data); |
3725 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
4268 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
3726 |
4269 |
3727 emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0; |
4270 emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0; |
3728 GST_OBJECT_UNLOCK (pad); |
4271 GST_OBJECT_UNLOCK (pad); |
3729 |
4272 |
3730 /* see if the signal should be emited, we emit before caps nego as |
4273 /* see if the signal should be emited, we emit before caps nego as |
3731 * we might drop the buffer and do capsnego for nothing. */ |
4274 * we might drop the buffer and do capsnego for nothing. */ |
3732 if (G_UNLIKELY (emit_signal)) { |
4275 if (G_UNLIKELY (emit_signal)) { |
3733 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer))) |
4276 if (G_LIKELY (is_buffer)) { |
3734 goto dropping; |
4277 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (data))) |
4278 goto dropping; |
|
4279 } else { |
|
4280 /* chain all groups in the buffer list one by one to avoid problems with |
|
4281 * buffer probes that push buffers or events */ |
|
4282 goto chain_groups; |
|
4283 } |
|
3735 } |
4284 } |
3736 |
4285 |
3737 /* we got a new datatype on the pad, see if it can handle it */ |
4286 /* we got a new datatype on the pad, see if it can handle it */ |
3738 if (G_UNLIKELY (caps_changed)) { |
4287 if (G_UNLIKELY (caps_changed)) { |
3739 GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps); |
4288 GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps); |
3744 /* NOTE: we read the chainfunc unlocked. |
4293 /* NOTE: we read the chainfunc unlocked. |
3745 * we cannot hold the lock for the pad so we might send |
4294 * we cannot hold the lock for the pad so we might send |
3746 * the data to the wrong function. This is not really a |
4295 * the data to the wrong function. This is not really a |
3747 * problem since functions are assigned at creation time |
4296 * problem since functions are assigned at creation time |
3748 * and don't change that often... */ |
4297 * and don't change that often... */ |
3749 if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL)) |
4298 if (G_LIKELY (is_buffer)) { |
3750 goto no_function; |
4299 GstPadChainFunction chainfunc; |
3751 |
4300 |
3752 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
4301 if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL)) |
3753 "calling chainfunction &%s", GST_DEBUG_FUNCPTR_NAME (chainfunc)); |
4302 goto no_function; |
3754 |
4303 |
3755 ret = chainfunc (pad, buffer); |
4304 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
3756 |
4305 "calling chainfunction &%s", GST_DEBUG_FUNCPTR_NAME (chainfunc)); |
3757 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
4306 |
3758 "called chainfunction &%s, returned %s", |
4307 ret = chainfunc (pad, GST_BUFFER_CAST (data)); |
3759 GST_DEBUG_FUNCPTR_NAME (chainfunc), gst_flow_get_name (ret)); |
4308 |
4309 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4310 "called chainfunction &%s, returned %s", |
|
4311 GST_DEBUG_FUNCPTR_NAME (chainfunc), gst_flow_get_name (ret)); |
|
4312 } else { |
|
4313 GstPadChainListFunction chainlistfunc; |
|
4314 |
|
4315 if (G_UNLIKELY ((chainlistfunc = GST_PAD_CHAINLISTFUNC (pad)) == NULL)) |
|
4316 goto chain_groups; |
|
4317 |
|
4318 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4319 "calling chainlistfunction &%s", |
|
4320 GST_DEBUG_FUNCPTR_NAME (chainlistfunc)); |
|
4321 |
|
4322 ret = chainlistfunc (pad, GST_BUFFER_LIST_CAST (data)); |
|
4323 |
|
4324 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4325 "called chainlistfunction &%s, returned %s", |
|
4326 GST_DEBUG_FUNCPTR_NAME (chainlistfunc), gst_flow_get_name (ret)); |
|
4327 } |
|
3760 |
4328 |
3761 GST_PAD_STREAM_UNLOCK (pad); |
4329 GST_PAD_STREAM_UNLOCK (pad); |
3762 |
4330 |
3763 return ret; |
4331 return ret; |
4332 |
|
4333 chain_groups: |
|
4334 { |
|
4335 GstBufferList *list; |
|
4336 GstBufferListIterator *it; |
|
4337 GstBuffer *group; |
|
4338 |
|
4339 GST_PAD_STREAM_UNLOCK (pad); |
|
4340 |
|
4341 GST_INFO_OBJECT (pad, "chaining each group in list as a merged buffer"); |
|
4342 |
|
4343 list = GST_BUFFER_LIST_CAST (data); |
|
4344 it = gst_buffer_list_iterate (list); |
|
4345 |
|
4346 ret = GST_FLOW_OK; |
|
4347 if (gst_buffer_list_iterator_next_group (it)) { |
|
4348 do { |
|
4349 group = gst_buffer_list_iterator_merge_group (it); |
|
4350 if (group == NULL) { |
|
4351 group = gst_buffer_new (); |
|
4352 GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group"); |
|
4353 } else { |
|
4354 GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining group"); |
|
4355 } |
|
4356 ret = gst_pad_chain_data_unchecked (pad, TRUE, group); |
|
4357 } while (ret == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it)); |
|
4358 } else { |
|
4359 GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group"); |
|
4360 ret = gst_pad_chain_data_unchecked (pad, TRUE, gst_buffer_new ()); |
|
4361 } |
|
4362 |
|
4363 gst_buffer_list_iterator_free (it); |
|
4364 gst_buffer_list_unref (list); |
|
4365 |
|
4366 return ret; |
|
4367 } |
|
3764 |
4368 |
3765 /* ERRORS */ |
4369 /* ERRORS */ |
3766 flushing: |
4370 flushing: |
3767 { |
4371 { |
3768 gst_buffer_unref (buffer); |
4372 gst_pad_data_unref (is_buffer, data); |
3769 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
4373 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
3770 "pushing, but pad was flushing"); |
4374 "pushing, but pad was flushing"); |
3771 GST_OBJECT_UNLOCK (pad); |
4375 GST_OBJECT_UNLOCK (pad); |
3772 GST_PAD_STREAM_UNLOCK (pad); |
4376 GST_PAD_STREAM_UNLOCK (pad); |
3773 return GST_FLOW_WRONG_STATE; |
4377 return GST_FLOW_WRONG_STATE; |
3774 } |
4378 } |
3775 dropping: |
4379 dropping: |
3776 { |
4380 { |
3777 gst_buffer_unref (buffer); |
4381 gst_pad_data_unref (is_buffer, data); |
3778 GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return"); |
4382 GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return"); |
3779 GST_PAD_STREAM_UNLOCK (pad); |
4383 GST_PAD_STREAM_UNLOCK (pad); |
3780 return GST_FLOW_OK; |
4384 return GST_FLOW_OK; |
3781 } |
4385 } |
3782 not_negotiated: |
4386 not_negotiated: |
3783 { |
4387 { |
3784 gst_buffer_unref (buffer); |
4388 gst_pad_data_unref (is_buffer, data); |
3785 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
4389 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
3786 "pushing buffer but pad did not accept"); |
4390 "pushing data but pad did not accept"); |
3787 GST_PAD_STREAM_UNLOCK (pad); |
4391 GST_PAD_STREAM_UNLOCK (pad); |
3788 return GST_FLOW_NOT_NEGOTIATED; |
4392 return GST_FLOW_NOT_NEGOTIATED; |
3789 } |
4393 } |
3790 no_function: |
4394 no_function: |
3791 { |
4395 { |
3792 gst_buffer_unref (buffer); |
4396 gst_pad_data_unref (is_buffer, data); |
3793 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
4397 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
3794 "pushing, but not chainhandler"); |
4398 "pushing, but not chainhandler"); |
3795 GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), |
4399 GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), |
3796 ("push on pad %s:%s but it has no chainfunction", |
4400 ("push on pad %s:%s but it has no chainfunction", |
3797 GST_DEBUG_PAD_NAME (pad))); |
4401 GST_DEBUG_PAD_NAME (pad))); |
3832 |
4436 |
3833 GstFlowReturn |
4437 GstFlowReturn |
3834 gst_pad_chain (GstPad * pad, GstBuffer * buffer) |
4438 gst_pad_chain (GstPad * pad, GstBuffer * buffer) |
3835 { |
4439 { |
3836 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
4440 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
3837 g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, |
4441 g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR); |
3838 GST_FLOW_ERROR); |
|
3839 g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); |
4442 g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); |
3840 |
4443 |
3841 return gst_pad_chain_unchecked (pad, buffer); |
4444 return gst_pad_chain_data_unchecked (pad, TRUE, buffer); |
3842 } |
4445 } |
3843 |
4446 |
3844 /** |
4447 /** |
3845 * gst_pad_push: |
4448 * gst_pad_chain_list: |
3846 * @pad: a source #GstPad, returns #GST_FLOW_ERROR if not. |
4449 * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. |
3847 * @buffer: the #GstBuffer to push returns GST_FLOW_ERROR if not. |
4450 * @list: the #GstBufferList to send, return GST_FLOW_ERROR if not. |
3848 * |
4451 * |
3849 * Pushes a buffer to the peer of @pad. |
4452 * Chain a bufferlist to @pad. |
3850 * |
4453 * |
3851 * This function will call an installed pad block before triggering any |
4454 * The function returns #GST_FLOW_WRONG_STATE if the pad was flushing. |
3852 * installed pad probes. |
4455 * |
3853 * |
4456 * If the caps on the first buffer of @list are different from the current |
3854 * If the caps on @buffer are different from the currently configured caps on |
4457 * caps on @pad, this function will call any setcaps function |
3855 * @pad, this function will call any installed setcaps function on @pad (see |
4458 * (see gst_pad_set_setcaps_function()) installed on @pad. If the new caps |
3856 * gst_pad_set_setcaps_function()). In case of failure to renegotiate the new |
4459 * are not acceptable for @pad, this function returns #GST_FLOW_NOT_NEGOTIATED. |
3857 * format, this function returns #GST_FLOW_NOT_NEGOTIATED. |
4460 * |
3858 * |
4461 * The function proceeds calling the chainlist function installed on @pad (see |
3859 * The function proceeds calling gst_pad_chain() on the peer pad and returns |
4462 * gst_pad_set_chain_list_function()) and the return value of that function is |
3860 * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will |
4463 * returned to the caller. #GST_FLOW_NOT_SUPPORTED is returned if @pad has no |
3861 * be returned. |
4464 * chainlist function. |
3862 * |
4465 * |
3863 * In all cases, success or failure, the caller loses its reference to @buffer |
4466 * In all cases, success or failure, the caller loses its reference to @list |
3864 * after calling this function. |
4467 * after calling this function. |
3865 * |
4468 * |
3866 * Returns: a #GstFlowReturn from the peer pad. |
|
3867 * |
|
3868 * MT safe. |
4469 * MT safe. |
3869 */ |
4470 * |
3870 #ifdef __SYMBIAN32__ |
4471 * Returns: a #GstFlowReturn from the pad. |
3871 EXPORT_C |
4472 * |
3872 #endif |
4473 * Since: 0.10.24 |
4474 */ |
|
4475 #ifdef __SYMBIAN32__ |
|
4476 EXPORT_C |
|
4477 #endif |
|
4478 |
|
3873 GstFlowReturn |
4479 GstFlowReturn |
3874 gst_pad_push (GstPad * pad, GstBuffer * buffer) |
4480 gst_pad_chain_list (GstPad * pad, GstBufferList * list) |
4481 { |
|
4482 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
|
4483 g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR); |
|
4484 g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR); |
|
4485 |
|
4486 return gst_pad_chain_data_unchecked (pad, FALSE, list); |
|
4487 } |
|
4488 |
|
4489 static GstFlowReturn |
|
4490 gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data) |
|
3875 { |
4491 { |
3876 GstPad *peer; |
4492 GstPad *peer; |
3877 GstFlowReturn ret; |
4493 GstFlowReturn ret; |
3878 |
|
3879 GstCaps *caps; |
4494 GstCaps *caps; |
3880 gboolean caps_changed; |
4495 gboolean caps_changed; |
3881 |
|
3882 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
|
3883 g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC, GST_FLOW_ERROR); |
|
3884 g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); |
|
3885 |
4496 |
3886 GST_OBJECT_LOCK (pad); |
4497 GST_OBJECT_LOCK (pad); |
3887 |
4498 |
3888 /* FIXME: this check can go away; pad_set_blocked could be implemented with |
4499 /* FIXME: this check can go away; pad_set_blocked could be implemented with |
3889 * probes completely or probes with an extended pad block. */ |
4500 * probes completely or probes with an extended pad block. */ |
3895 * emit in the _chain() function */ |
4506 * emit in the _chain() function */ |
3896 if (G_UNLIKELY (GST_PAD_DO_BUFFER_SIGNALS (pad) > 0)) { |
4507 if (G_UNLIKELY (GST_PAD_DO_BUFFER_SIGNALS (pad) > 0)) { |
3897 /* unlock before emitting */ |
4508 /* unlock before emitting */ |
3898 GST_OBJECT_UNLOCK (pad); |
4509 GST_OBJECT_UNLOCK (pad); |
3899 |
4510 |
3900 /* if the signal handler returned FALSE, it means we should just drop the |
4511 if (G_LIKELY (is_buffer)) { |
3901 * buffer */ |
4512 /* if the signal handler returned FALSE, it means we should just drop the |
3902 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer))) |
4513 * buffer */ |
3903 goto dropped; |
4514 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (data))) |
3904 |
4515 goto dropped; |
4516 } else { |
|
4517 /* push all buffers in the list */ |
|
4518 goto push_groups; |
|
4519 } |
|
3905 GST_OBJECT_LOCK (pad); |
4520 GST_OBJECT_LOCK (pad); |
3906 } |
4521 } |
3907 |
4522 |
3908 if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) |
4523 if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) |
3909 goto not_linked; |
4524 goto not_linked; |
3910 |
4525 |
4526 /* Before pushing the buffer to the peer pad, ensure that caps |
|
4527 * are set on this pad */ |
|
4528 caps = gst_pad_data_get_caps (is_buffer, data); |
|
4529 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
|
4530 |
|
3911 /* take ref to peer pad before releasing the lock */ |
4531 /* take ref to peer pad before releasing the lock */ |
3912 gst_object_ref (peer); |
4532 gst_object_ref (peer); |
3913 |
|
3914 /* Before pushing the buffer to the peer pad, ensure that caps |
|
3915 * are set on this pad */ |
|
3916 caps = GST_BUFFER_CAPS (buffer); |
|
3917 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
|
3918 |
4533 |
3919 GST_OBJECT_UNLOCK (pad); |
4534 GST_OBJECT_UNLOCK (pad); |
3920 |
4535 |
3921 /* we got a new datatype from the pad, it had better handle it */ |
4536 /* we got a new datatype from the pad, it had better handle it */ |
3922 if (G_UNLIKELY (caps_changed)) { |
4537 if (G_UNLIKELY (caps_changed)) { |
3925 GST_PAD_CAPS (pad), caps, caps); |
4540 GST_PAD_CAPS (pad), caps, caps); |
3926 if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE))) |
4541 if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE))) |
3927 goto not_negotiated; |
4542 goto not_negotiated; |
3928 } |
4543 } |
3929 |
4544 |
3930 ret = gst_pad_chain_unchecked (peer, buffer); |
4545 ret = gst_pad_chain_data_unchecked (peer, is_buffer, data); |
3931 |
4546 |
3932 gst_object_unref (peer); |
4547 gst_object_unref (peer); |
3933 |
4548 |
3934 return ret; |
4549 return ret; |
4550 |
|
4551 push_groups: |
|
4552 { |
|
4553 GstBufferList *list; |
|
4554 GstBufferListIterator *it; |
|
4555 GstBuffer *group; |
|
4556 |
|
4557 GST_INFO_OBJECT (pad, "pushing each group in list as a merged buffer"); |
|
4558 |
|
4559 list = GST_BUFFER_LIST_CAST (data); |
|
4560 it = gst_buffer_list_iterate (list); |
|
4561 |
|
4562 ret = GST_FLOW_OK; |
|
4563 if (gst_buffer_list_iterator_next_group (it)) { |
|
4564 do { |
|
4565 group = gst_buffer_list_iterator_merge_group (it); |
|
4566 if (group == NULL) { |
|
4567 group = gst_buffer_new (); |
|
4568 GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing empty group"); |
|
4569 } else { |
|
4570 GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing group"); |
|
4571 } |
|
4572 ret = gst_pad_push_data (pad, TRUE, group); |
|
4573 } while (ret == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it)); |
|
4574 } else { |
|
4575 GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing empty group"); |
|
4576 ret = gst_pad_push_data (pad, TRUE, gst_buffer_new ()); |
|
4577 } |
|
4578 |
|
4579 gst_buffer_list_iterator_free (it); |
|
4580 gst_buffer_list_unref (list); |
|
4581 |
|
4582 return ret; |
|
4583 } |
|
3935 |
4584 |
3936 /* ERROR recovery here */ |
4585 /* ERROR recovery here */ |
3937 flushed: |
4586 flushed: |
3938 { |
4587 { |
3939 gst_buffer_unref (buffer); |
4588 gst_pad_data_unref (is_buffer, data); |
3940 GST_DEBUG_OBJECT (pad, "pad block stopped by flush"); |
4589 GST_DEBUG_OBJECT (pad, "pad block stopped by flush"); |
3941 GST_OBJECT_UNLOCK (pad); |
4590 GST_OBJECT_UNLOCK (pad); |
3942 return ret; |
4591 return ret; |
3943 } |
4592 } |
3944 dropped: |
4593 dropped: |
3945 { |
4594 { |
3946 gst_buffer_unref (buffer); |
4595 gst_pad_data_unref (is_buffer, data); |
3947 GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return"); |
4596 GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return"); |
3948 return GST_FLOW_OK; |
4597 return GST_FLOW_OK; |
3949 } |
4598 } |
3950 not_linked: |
4599 not_linked: |
3951 { |
4600 { |
3952 gst_buffer_unref (buffer); |
4601 gst_pad_data_unref (is_buffer, data); |
3953 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
4602 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
3954 "pushing, but it was not linked"); |
4603 "pushing, but it was not linked"); |
3955 GST_OBJECT_UNLOCK (pad); |
4604 GST_OBJECT_UNLOCK (pad); |
3956 return GST_FLOW_NOT_LINKED; |
4605 return GST_FLOW_NOT_LINKED; |
3957 } |
4606 } |
3958 not_negotiated: |
4607 not_negotiated: |
3959 { |
4608 { |
3960 gst_buffer_unref (buffer); |
4609 gst_pad_data_unref (is_buffer, data); |
3961 gst_object_unref (peer); |
4610 gst_object_unref (peer); |
3962 GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, |
4611 GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, |
3963 "element pushed buffer then refused to accept the caps"); |
4612 "element pushed data then refused to accept the caps"); |
3964 return GST_FLOW_NOT_NEGOTIATED; |
4613 return GST_FLOW_NOT_NEGOTIATED; |
3965 } |
4614 } |
4615 } |
|
4616 |
|
4617 /** |
|
4618 * gst_pad_push: |
|
4619 * @pad: a source #GstPad, returns #GST_FLOW_ERROR if not. |
|
4620 * @buffer: the #GstBuffer to push returns GST_FLOW_ERROR if not. |
|
4621 * |
|
4622 * Pushes a buffer to the peer of @pad. |
|
4623 * |
|
4624 * This function will call an installed pad block before triggering any |
|
4625 * installed pad probes. |
|
4626 * |
|
4627 * If the caps on @buffer are different from the currently configured caps on |
|
4628 * @pad, this function will call any installed setcaps function on @pad (see |
|
4629 * gst_pad_set_setcaps_function()). In case of failure to renegotiate the new |
|
4630 * format, this function returns #GST_FLOW_NOT_NEGOTIATED. |
|
4631 * |
|
4632 * The function proceeds calling gst_pad_chain() on the peer pad and returns |
|
4633 * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will |
|
4634 * be returned. |
|
4635 * |
|
4636 * In all cases, success or failure, the caller loses its reference to @buffer |
|
4637 * after calling this function. |
|
4638 * |
|
4639 * Returns: a #GstFlowReturn from the peer pad. |
|
4640 * |
|
4641 * MT safe. |
|
4642 */ |
|
4643 #ifdef __SYMBIAN32__ |
|
4644 EXPORT_C |
|
4645 #endif |
|
4646 |
|
4647 GstFlowReturn |
|
4648 gst_pad_push (GstPad * pad, GstBuffer * buffer) |
|
4649 { |
|
4650 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
|
4651 g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); |
|
4652 g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); |
|
4653 |
|
4654 return gst_pad_push_data (pad, TRUE, buffer); |
|
4655 } |
|
4656 |
|
4657 /** |
|
4658 * gst_pad_push_list: |
|
4659 * @pad: a source #GstPad, returns #GST_FLOW_ERROR if not. |
|
4660 * @list: the #GstBufferList to push returns GST_FLOW_ERROR if not. |
|
4661 * |
|
4662 * Pushes a buffer list to the peer of @pad. |
|
4663 * |
|
4664 * This function will call an installed pad block before triggering any |
|
4665 * installed pad probes. |
|
4666 * |
|
4667 * If the caps on the first buffer in the first group of @list are different |
|
4668 * from the currently configured caps on @pad, this function will call any |
|
4669 * installed setcaps function on @pad (see gst_pad_set_setcaps_function()). In |
|
4670 * case of failure to renegotiate the new format, this function returns |
|
4671 * #GST_FLOW_NOT_NEGOTIATED. |
|
4672 * |
|
4673 * If there are any probes installed on @pad every group of the buffer list |
|
4674 * will be merged into a normal #GstBuffer and pushed via gst_pad_push and the |
|
4675 * buffer list will be unreffed. |
|
4676 * |
|
4677 * The function proceeds calling the chain function on the peer pad and returns |
|
4678 * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will |
|
4679 * be returned. If the peer pad does not have any installed chainlist function |
|
4680 * every group buffer of the list will be merged into a normal #GstBuffer and |
|
4681 * chained via gst_pad_chain(). |
|
4682 * |
|
4683 * In all cases, success or failure, the caller loses its reference to @list |
|
4684 * after calling this function. |
|
4685 * |
|
4686 * Returns: a #GstFlowReturn from the peer pad. |
|
4687 * |
|
4688 * MT safe. |
|
4689 * |
|
4690 * Since: 0.10.24 |
|
4691 */ |
|
4692 #ifdef __SYMBIAN32__ |
|
4693 EXPORT_C |
|
4694 #endif |
|
4695 |
|
4696 GstFlowReturn |
|
4697 gst_pad_push_list (GstPad * pad, GstBufferList * list) |
|
4698 { |
|
4699 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
|
4700 g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); |
|
4701 g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR); |
|
4702 |
|
4703 return gst_pad_push_data (pad, FALSE, list); |
|
3966 } |
4704 } |
3967 |
4705 |
3968 /** |
4706 /** |
3969 * gst_pad_check_pull_range: |
4707 * gst_pad_check_pull_range: |
3970 * @pad: a sink #GstPad. |
4708 * @pad: a sink #GstPad. |
3993 GstPadCheckGetRangeFunction checkgetrangefunc; |
4731 GstPadCheckGetRangeFunction checkgetrangefunc; |
3994 |
4732 |
3995 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
4733 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
3996 |
4734 |
3997 GST_OBJECT_LOCK (pad); |
4735 GST_OBJECT_LOCK (pad); |
3998 if (GST_PAD_DIRECTION (pad) != GST_PAD_SINK) |
4736 if (!GST_PAD_IS_SINK (pad)) |
3999 goto wrong_direction; |
4737 goto wrong_direction; |
4000 |
4738 |
4001 if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) |
4739 if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) |
4002 goto not_connected; |
4740 goto not_connected; |
4003 |
4741 |
4052 * Calls the getrange function of @pad, see #GstPadGetRangeFunction for a |
4790 * Calls the getrange function of @pad, see #GstPadGetRangeFunction for a |
4053 * description of a getrange function. If @pad has no getrange function |
4791 * description of a getrange function. If @pad has no getrange function |
4054 * installed (see gst_pad_set_getrange_function()) this function returns |
4792 * installed (see gst_pad_set_getrange_function()) this function returns |
4055 * #GST_FLOW_NOT_SUPPORTED. |
4793 * #GST_FLOW_NOT_SUPPORTED. |
4056 * |
4794 * |
4057 * @buffer's caps must either be unset or the same as what is already |
|
4058 * configured on @pad. Renegotiation within a running pull-mode pipeline is not |
|
4059 * supported. |
|
4060 * |
|
4061 * This is a lowlevel function. Usualy gst_pad_pull_range() is used. |
4795 * This is a lowlevel function. Usualy gst_pad_pull_range() is used. |
4062 * |
4796 * |
4063 * Returns: a #GstFlowReturn from the pad. |
4797 * Returns: a #GstFlowReturn from the pad. |
4064 * |
4798 * |
4065 * MT safe. |
4799 * MT safe. |
4073 GstBuffer ** buffer) |
4807 GstBuffer ** buffer) |
4074 { |
4808 { |
4075 GstFlowReturn ret; |
4809 GstFlowReturn ret; |
4076 GstPadGetRangeFunction getrangefunc; |
4810 GstPadGetRangeFunction getrangefunc; |
4077 gboolean emit_signal; |
4811 gboolean emit_signal; |
4812 GstCaps *caps; |
|
4813 gboolean caps_changed; |
|
4078 |
4814 |
4079 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
4815 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
4080 g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC, GST_FLOW_ERROR); |
4816 g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); |
4081 g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); |
4817 g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); |
4082 |
4818 |
4083 GST_PAD_STREAM_LOCK (pad); |
4819 GST_PAD_STREAM_LOCK (pad); |
4084 |
4820 |
4085 GST_OBJECT_LOCK (pad); |
4821 GST_OBJECT_LOCK (pad); |
4105 goto dropping; |
4841 goto dropping; |
4106 } |
4842 } |
4107 |
4843 |
4108 GST_PAD_STREAM_UNLOCK (pad); |
4844 GST_PAD_STREAM_UNLOCK (pad); |
4109 |
4845 |
4110 if (G_LIKELY (ret == GST_FLOW_OK)) { |
4846 if (G_UNLIKELY (ret != GST_FLOW_OK)) |
4111 GstCaps *caps; |
4847 goto get_range_failed; |
4112 gboolean caps_changed; |
4848 |
4113 |
4849 GST_OBJECT_LOCK (pad); |
4114 GST_OBJECT_LOCK (pad); |
4850 /* Before pushing the buffer to the peer pad, ensure that caps |
4115 /* Before pushing the buffer to the peer pad, ensure that caps |
4851 * are set on this pad */ |
4116 * are set on this pad */ |
4852 caps = GST_BUFFER_CAPS (*buffer); |
4117 caps = GST_BUFFER_CAPS (*buffer); |
4853 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
4118 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
4854 GST_OBJECT_UNLOCK (pad); |
4119 GST_OBJECT_UNLOCK (pad); |
4855 |
4120 |
4856 if (G_UNLIKELY (caps_changed)) { |
4121 /* we got a new datatype from the pad not supported in a running pull-mode |
4857 GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps); |
4122 * pipeline */ |
4858 /* this should usually work because the element produced the buffer */ |
4123 if (G_UNLIKELY (caps_changed)) |
4859 if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE))) |
4124 goto not_negotiated; |
4860 goto not_negotiated; |
4125 } |
4861 } |
4126 |
|
4127 return ret; |
4862 return ret; |
4128 |
4863 |
4129 /* ERRORS */ |
4864 /* ERRORS */ |
4130 flushing: |
4865 flushing: |
4131 { |
4866 { |
4150 GST_PAD_STREAM_UNLOCK (pad); |
4885 GST_PAD_STREAM_UNLOCK (pad); |
4151 gst_buffer_unref (*buffer); |
4886 gst_buffer_unref (*buffer); |
4152 *buffer = NULL; |
4887 *buffer = NULL; |
4153 return GST_FLOW_UNEXPECTED; |
4888 return GST_FLOW_UNEXPECTED; |
4154 } |
4889 } |
4890 get_range_failed: |
|
4891 { |
|
4892 *buffer = NULL; |
|
4893 GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4894 "getrange failed %s", gst_flow_get_name (ret)); |
|
4895 return ret; |
|
4896 } |
|
4155 not_negotiated: |
4897 not_negotiated: |
4156 { |
4898 { |
4157 /* ideally we want to use the commented-out code, but currently demuxers |
|
4158 * and typefind do not follow part-negotiation.txt. When switching into |
|
4159 * pull mode, typefind should probably return the found caps from |
|
4160 * getcaps(), and demuxers should do the setcaps(). */ |
|
4161 |
|
4162 #if 0 |
|
4163 gst_buffer_unref (*buffer); |
4899 gst_buffer_unref (*buffer); |
4164 *buffer = NULL; |
4900 *buffer = NULL; |
4165 GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad, |
4901 GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad, |
4166 "getrange returned buffer of different caps"); |
4902 "getrange returned buffer of unaccaptable caps"); |
4167 return GST_FLOW_NOT_NEGOTIATED; |
4903 return GST_FLOW_NOT_NEGOTIATED; |
4168 #endif |
|
4169 GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4170 "getrange returned buffer of different caps"); |
|
4171 return ret; |
|
4172 } |
4904 } |
4173 } |
4905 } |
4174 |
4906 |
4175 |
4907 |
4176 /** |
4908 /** |
4211 GstBuffer ** buffer) |
4943 GstBuffer ** buffer) |
4212 { |
4944 { |
4213 GstPad *peer; |
4945 GstPad *peer; |
4214 GstFlowReturn ret; |
4946 GstFlowReturn ret; |
4215 gboolean emit_signal; |
4947 gboolean emit_signal; |
4948 GstCaps *caps; |
|
4949 gboolean caps_changed; |
|
4216 |
4950 |
4217 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
4951 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
4218 g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, |
4952 g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR); |
4219 GST_FLOW_ERROR); |
|
4220 g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); |
4953 g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); |
4221 |
4954 |
4222 GST_OBJECT_LOCK (pad); |
4955 GST_OBJECT_LOCK (pad); |
4223 |
4956 |
4224 while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) |
4957 while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) |
4236 |
4969 |
4237 ret = gst_pad_get_range (peer, offset, size, buffer); |
4970 ret = gst_pad_get_range (peer, offset, size, buffer); |
4238 |
4971 |
4239 gst_object_unref (peer); |
4972 gst_object_unref (peer); |
4240 |
4973 |
4974 if (G_UNLIKELY (ret != GST_FLOW_OK)) |
|
4975 goto pull_range_failed; |
|
4976 |
|
4241 /* can only fire the signal if we have a valid buffer */ |
4977 /* can only fire the signal if we have a valid buffer */ |
4242 if (G_UNLIKELY (emit_signal) && (ret == GST_FLOW_OK)) { |
4978 if (G_UNLIKELY (emit_signal)) { |
4243 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer))) |
4979 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer))) |
4244 goto dropping; |
4980 goto dropping; |
4245 } |
4981 } |
4246 |
4982 |
4247 if (G_LIKELY (ret == GST_FLOW_OK)) { |
4983 GST_OBJECT_LOCK (pad); |
4248 GstCaps *caps; |
4984 /* Before pushing the buffer to the peer pad, ensure that caps |
4249 gboolean caps_changed; |
4985 * are set on this pad */ |
4250 |
4986 caps = GST_BUFFER_CAPS (*buffer); |
4251 GST_OBJECT_LOCK (pad); |
4987 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
4252 /* Before pushing the buffer to the peer pad, ensure that caps |
4988 GST_OBJECT_UNLOCK (pad); |
4253 * are set on this pad */ |
4989 |
4254 caps = GST_BUFFER_CAPS (*buffer); |
4990 /* we got a new datatype on the pad, see if it can handle it */ |
4255 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
4991 if (G_UNLIKELY (caps_changed)) { |
4256 GST_OBJECT_UNLOCK (pad); |
4992 GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps); |
4257 |
4993 if (G_UNLIKELY (!gst_pad_configure_sink (pad, caps))) |
4258 /* we got a new datatype on the pad, see if it can handle it */ |
|
4259 if (G_UNLIKELY (caps_changed)) |
|
4260 goto not_negotiated; |
4994 goto not_negotiated; |
4261 } |
4995 } |
4262 |
|
4263 return ret; |
4996 return ret; |
4264 |
4997 |
4265 /* ERROR recovery here */ |
4998 /* ERROR recovery here */ |
4266 not_connected: |
4999 not_connected: |
4267 { |
5000 { |
4268 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
5001 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
4269 "pulling range, but it was not linked"); |
5002 "pulling range, but it was not linked"); |
4270 GST_OBJECT_UNLOCK (pad); |
5003 GST_OBJECT_UNLOCK (pad); |
4271 return GST_FLOW_NOT_LINKED; |
5004 return GST_FLOW_NOT_LINKED; |
5005 } |
|
5006 pull_range_failed: |
|
5007 { |
|
5008 *buffer = NULL; |
|
5009 GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad, |
|
5010 "pullrange failed %s", gst_flow_get_name (ret)); |
|
5011 return ret; |
|
4272 } |
5012 } |
4273 dropping: |
5013 dropping: |
4274 { |
5014 { |
4275 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
5015 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
4276 "Dropping data after FALSE probe return"); |
5016 "Dropping data after FALSE probe return"); |
4278 *buffer = NULL; |
5018 *buffer = NULL; |
4279 return GST_FLOW_UNEXPECTED; |
5019 return GST_FLOW_UNEXPECTED; |
4280 } |
5020 } |
4281 not_negotiated: |
5021 not_negotiated: |
4282 { |
5022 { |
4283 /* ideally we want to use the commented-out code, but currently demuxers |
|
4284 * and typefind do not follow part-negotiation.txt. When switching into |
|
4285 * pull mode, typefind should probably return the found caps from |
|
4286 * getcaps(), and demuxers should do the setcaps(). */ |
|
4287 |
|
4288 #if 0 |
|
4289 gst_buffer_unref (*buffer); |
5023 gst_buffer_unref (*buffer); |
4290 *buffer = NULL; |
5024 *buffer = NULL; |
4291 GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad, |
5025 GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad, |
4292 "pullrange returned buffer of different caps"); |
5026 "pullrange returned buffer of different caps"); |
4293 return GST_FLOW_NOT_NEGOTIATED; |
5027 return GST_FLOW_NOT_NEGOTIATED; |
4294 #endif |
|
4295 GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4296 "pullrange returned buffer of different caps"); |
|
4297 return ret; |
|
4298 } |
5028 } |
4299 } |
5029 } |
4300 |
5030 |
4301 /** |
5031 /** |
4302 * gst_pad_push_event: |
5032 * gst_pad_push_event: |
4621 gst_pad_get_element_private (GstPad * pad) |
5351 gst_pad_get_element_private (GstPad * pad) |
4622 { |
5352 { |
4623 return pad->element_private; |
5353 return pad->element_private; |
4624 } |
5354 } |
4625 |
5355 |
5356 static void |
|
5357 do_stream_status (GstPad * pad, GstStreamStatusType type, |
|
5358 GThread * thread, GstTask * task) |
|
5359 { |
|
5360 GstElement *parent; |
|
5361 |
|
5362 GST_DEBUG_OBJECT (pad, "doing stream-status %d", type); |
|
5363 |
|
5364 if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (pad)))) { |
|
5365 if (GST_IS_ELEMENT (parent)) { |
|
5366 GstMessage *message; |
|
5367 GValue value = { 0 }; |
|
5368 |
|
5369 message = gst_message_new_stream_status (GST_OBJECT_CAST (pad), |
|
5370 type, parent); |
|
5371 |
|
5372 g_value_init (&value, GST_TYPE_TASK); |
|
5373 g_value_set_object (&value, task); |
|
5374 gst_message_set_stream_status_object (message, &value); |
|
5375 g_value_unset (&value); |
|
5376 |
|
5377 GST_DEBUG_OBJECT (pad, "posting stream-status %d", type); |
|
5378 gst_element_post_message (parent, message); |
|
5379 } |
|
5380 gst_object_unref (parent); |
|
5381 } |
|
5382 } |
|
5383 |
|
5384 static void |
|
5385 pad_enter_thread (GstTask * task, GThread * thread, gpointer user_data) |
|
5386 { |
|
5387 do_stream_status (GST_PAD_CAST (user_data), GST_STREAM_STATUS_TYPE_ENTER, |
|
5388 thread, task); |
|
5389 } |
|
5390 |
|
5391 static void |
|
5392 pad_leave_thread (GstTask * task, GThread * thread, gpointer user_data) |
|
5393 { |
|
5394 do_stream_status (GST_PAD_CAST (user_data), GST_STREAM_STATUS_TYPE_LEAVE, |
|
5395 thread, task); |
|
5396 } |
|
5397 |
|
5398 static GstTaskThreadCallbacks thr_callbacks = { |
|
5399 pad_enter_thread, |
|
5400 pad_leave_thread, |
|
5401 }; |
|
5402 |
|
4626 /** |
5403 /** |
4627 * gst_pad_start_task: |
5404 * gst_pad_start_task: |
4628 * @pad: the #GstPad to start the task of |
5405 * @pad: the #GstPad to start the task of |
4629 * @func: the task function to call |
5406 * @func: the task function to call |
4630 * @data: data passed to the task function |
5407 * @data: data passed to the task function |
4642 |
5419 |
4643 gboolean |
5420 gboolean |
4644 gst_pad_start_task (GstPad * pad, GstTaskFunction func, gpointer data) |
5421 gst_pad_start_task (GstPad * pad, GstTaskFunction func, gpointer data) |
4645 { |
5422 { |
4646 GstTask *task; |
5423 GstTask *task; |
5424 gboolean res; |
|
4647 |
5425 |
4648 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
5426 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
4649 g_return_val_if_fail (func != NULL, FALSE); |
5427 g_return_val_if_fail (func != NULL, FALSE); |
4650 |
5428 |
4651 GST_DEBUG_OBJECT (pad, "start task"); |
5429 GST_DEBUG_OBJECT (pad, "start task"); |
4653 GST_OBJECT_LOCK (pad); |
5431 GST_OBJECT_LOCK (pad); |
4654 task = GST_PAD_TASK (pad); |
5432 task = GST_PAD_TASK (pad); |
4655 if (task == NULL) { |
5433 if (task == NULL) { |
4656 task = gst_task_create (func, data); |
5434 task = gst_task_create (func, data); |
4657 gst_task_set_lock (task, GST_PAD_GET_STREAM_LOCK (pad)); |
5435 gst_task_set_lock (task, GST_PAD_GET_STREAM_LOCK (pad)); |
5436 gst_task_set_thread_callbacks (task, &thr_callbacks, pad, NULL); |
|
5437 GST_DEBUG_OBJECT (pad, "created task"); |
|
4658 GST_PAD_TASK (pad) = task; |
5438 GST_PAD_TASK (pad) = task; |
4659 GST_DEBUG_OBJECT (pad, "created task"); |
5439 gst_object_ref (task); |
4660 } |
5440 /* release lock to post the message */ |
4661 gst_task_start (task); |
5441 GST_OBJECT_UNLOCK (pad); |
5442 |
|
5443 do_stream_status (pad, GST_STREAM_STATUS_TYPE_CREATE, NULL, task); |
|
5444 |
|
5445 gst_object_unref (task); |
|
5446 |
|
5447 GST_OBJECT_LOCK (pad); |
|
5448 /* nobody else is supposed to have changed the pad now */ |
|
5449 if (GST_PAD_TASK (pad) != task) |
|
5450 goto concurrent_stop; |
|
5451 } |
|
5452 res = gst_task_set_state (task, GST_TASK_STARTED); |
|
4662 GST_OBJECT_UNLOCK (pad); |
5453 GST_OBJECT_UNLOCK (pad); |
4663 |
5454 |
4664 return TRUE; |
5455 return res; |
5456 |
|
5457 /* ERRORS */ |
|
5458 concurrent_stop: |
|
5459 { |
|
5460 GST_OBJECT_UNLOCK (pad); |
|
5461 return TRUE; |
|
5462 } |
|
4665 } |
5463 } |
4666 |
5464 |
4667 /** |
5465 /** |
4668 * gst_pad_pause_task: |
5466 * gst_pad_pause_task: |
4669 * @pad: the #GstPad to pause the task of |
5467 * @pad: the #GstPad to pause the task of |
4681 |
5479 |
4682 gboolean |
5480 gboolean |
4683 gst_pad_pause_task (GstPad * pad) |
5481 gst_pad_pause_task (GstPad * pad) |
4684 { |
5482 { |
4685 GstTask *task; |
5483 GstTask *task; |
5484 gboolean res; |
|
4686 |
5485 |
4687 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
5486 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
4688 |
5487 |
4689 GST_DEBUG_OBJECT (pad, "pause task"); |
5488 GST_DEBUG_OBJECT (pad, "pause task"); |
4690 |
5489 |
4691 GST_OBJECT_LOCK (pad); |
5490 GST_OBJECT_LOCK (pad); |
4692 task = GST_PAD_TASK (pad); |
5491 task = GST_PAD_TASK (pad); |
4693 if (task == NULL) |
5492 if (task == NULL) |
4694 goto no_task; |
5493 goto no_task; |
4695 gst_task_pause (task); |
5494 res = gst_task_set_state (task, GST_TASK_PAUSED); |
4696 GST_OBJECT_UNLOCK (pad); |
5495 GST_OBJECT_UNLOCK (pad); |
4697 |
5496 |
4698 /* wait for task function to finish, this lock is recursive so it does nothing |
5497 /* wait for task function to finish, this lock is recursive so it does nothing |
4699 * when the pause is called from the task itself */ |
5498 * when the pause is called from the task itself */ |
4700 GST_PAD_STREAM_LOCK (pad); |
5499 GST_PAD_STREAM_LOCK (pad); |
4701 GST_PAD_STREAM_UNLOCK (pad); |
5500 GST_PAD_STREAM_UNLOCK (pad); |
4702 |
5501 |
4703 return TRUE; |
5502 return res; |
4704 |
5503 |
4705 no_task: |
5504 no_task: |
4706 { |
5505 { |
4707 GST_DEBUG_OBJECT (pad, "pad has no task"); |
5506 GST_DEBUG_OBJECT (pad, "pad has no task"); |
4708 GST_OBJECT_UNLOCK (pad); |
5507 GST_OBJECT_UNLOCK (pad); |
4732 |
5531 |
4733 gboolean |
5532 gboolean |
4734 gst_pad_stop_task (GstPad * pad) |
5533 gst_pad_stop_task (GstPad * pad) |
4735 { |
5534 { |
4736 GstTask *task; |
5535 GstTask *task; |
5536 gboolean res; |
|
4737 |
5537 |
4738 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
5538 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
4739 |
5539 |
4740 GST_DEBUG_OBJECT (pad, "stop task"); |
5540 GST_DEBUG_OBJECT (pad, "stop task"); |
4741 |
5541 |
4742 GST_OBJECT_LOCK (pad); |
5542 GST_OBJECT_LOCK (pad); |
4743 task = GST_PAD_TASK (pad); |
5543 task = GST_PAD_TASK (pad); |
4744 if (task == NULL) |
5544 if (task == NULL) |
4745 goto no_task; |
5545 goto no_task; |
4746 GST_PAD_TASK (pad) = NULL; |
5546 GST_PAD_TASK (pad) = NULL; |
4747 gst_task_stop (task); |
5547 res = gst_task_set_state (task, GST_TASK_STOPPED); |
4748 GST_OBJECT_UNLOCK (pad); |
5548 GST_OBJECT_UNLOCK (pad); |
4749 |
5549 |
4750 GST_PAD_STREAM_LOCK (pad); |
5550 GST_PAD_STREAM_LOCK (pad); |
4751 GST_PAD_STREAM_UNLOCK (pad); |
5551 GST_PAD_STREAM_UNLOCK (pad); |
4752 |
5552 |
4753 if (!gst_task_join (task)) |
5553 if (!gst_task_join (task)) |
4754 goto join_failed; |
5554 goto join_failed; |
4755 |
5555 |
4756 gst_object_unref (task); |
5556 gst_object_unref (task); |
4757 |
5557 |
4758 return TRUE; |
5558 return res; |
4759 |
5559 |
4760 no_task: |
5560 no_task: |
4761 { |
5561 { |
4762 GST_DEBUG_OBJECT (pad, "no task"); |
5562 GST_DEBUG_OBJECT (pad, "no task"); |
4763 GST_OBJECT_UNLOCK (pad); |
5563 GST_OBJECT_UNLOCK (pad); |