changeset 16 | 8e837d1bf446 |
parent 0 | 0e761a78d257 |
child 30 | 7e817e7e631c |
15:4b0c6ed43234 | 16:8e837d1bf446 |
---|---|
19 * Boston, MA 02111-1307, USA. |
19 * Boston, MA 02111-1307, USA. |
20 */ |
20 */ |
21 |
21 |
22 /** |
22 /** |
23 * SECTION:element-multifdsink |
23 * SECTION:element-multifdsink |
24 * @short_description: Send data to multiple file descriptors |
|
25 * @see_also: tcpserversink |
24 * @see_also: tcpserversink |
26 * |
25 * |
27 * <refsect2> |
|
28 * <para> |
|
29 * This plugin writes incoming data to a set of file descriptors. The |
26 * This plugin writes incoming data to a set of file descriptors. The |
30 * file descriptors can be added to multifdsink by emitting the "add" signal. |
27 * file descriptors can be added to multifdsink by emitting the #GstMultiFdSink::add signal. |
31 * For each descriptor added, the "client-added" signal will be called. |
28 * For each descriptor added, the #GstMultiFdSink::client-added signal will be called. |
32 * </para> |
29 * |
33 * <para> |
30 * As of version 0.10.8, a client can also be added with the #GstMultiFdSink::add-full signal |
34 * As of version 0.10.8, a client can also be added with the "add-full" signal |
|
35 * that allows for more control over what and how much data a client |
31 * that allows for more control over what and how much data a client |
36 * initially receives. |
32 * initially receives. |
37 * </para> |
33 * |
38 * <para> |
34 * Clients can be removed from multifdsink by emitting the #GstMultiFdSink::remove signal. For |
39 * Clients can be removed from multifdsink by emitting the "remove" signal. For |
35 * each descriptor removed, the #GstMultiFdSink::client-removed signal will be called. The |
40 * each descriptor removed, the "client-removed" signal will be called. The |
36 * #GstMultiFdSink::client-removed signal can also be fired when multifdsink decides that a |
41 * "client-removed" signal can also be fired when multifdsink decides that a |
|
42 * client is not active anymore or, depending on the value of the |
37 * client is not active anymore or, depending on the value of the |
43 * "recover-policy" property, if the client is reading too slowly. |
38 * #GstMultiFdSink:recover-policy property, if the client is reading too slowly. |
44 * In all cases, multifdsink will never close a file descriptor itself. |
39 * In all cases, multifdsink will never close a file descriptor itself. |
45 * The user of multifdsink is responsible for closing all file descriptors. |
40 * The user of multifdsink is responsible for closing all file descriptors. |
46 * This can for example be done in response to the "client-fd-removed" signal. |
41 * This can for example be done in response to the #GstMultiFdSink::client-fd-removed signal. |
47 * Note that multifdsink still has a reference to the file descriptor when the |
42 * Note that multifdsink still has a reference to the file descriptor when the |
48 * "client-removed" signal is emitted, so that "get-stats" can be performed on |
43 * #GstMultiFdSink::client-removed signal is emitted, so that "get-stats" can be performed on |
49 * the descriptor; it is therefore not safe to close the file descriptor in |
44 * the descriptor; it is therefore not safe to close the file descriptor in |
50 * the "client-removed" signal handler, and you should use the |
45 * the #GstMultiFdSink::client-removed signal handler, and you should use the |
51 * "client-fd-removed" signal to safely close the fd. |
46 * #GstMultiFdSink::client-fd-removed signal to safely close the fd. |
52 * </para> |
47 * |
53 * <para> |
|
54 * Multifdsink internally keeps a queue of the incoming buffers and uses a |
48 * Multifdsink internally keeps a queue of the incoming buffers and uses a |
55 * separate thread to send the buffers to the clients. This ensures that no |
49 * separate thread to send the buffers to the clients. This ensures that no |
56 * client write can block the pipeline and that clients can read with different |
50 * client write can block the pipeline and that clients can read with different |
57 * speeds. |
51 * speeds. |
58 * </para> |
52 * |
59 * <para> |
53 * When adding a client to multifdsink, the #GstMultiFdSink:sync-method property will define |
60 * When adding a client to multifdsink, the "sync-method" property will define |
|
61 * which buffer in the queued buffers will be sent first to the client. Clients |
54 * which buffer in the queued buffers will be sent first to the client. Clients |
62 * can be sent the most recent buffer (which might not be decodable by the |
55 * can be sent the most recent buffer (which might not be decodable by the |
63 * client if it is not a keyframe), the next keyframe received in |
56 * client if it is not a keyframe), the next keyframe received in |
64 * multifdsink (which can take some time depending on the keyframe rate), or the |
57 * multifdsink (which can take some time depending on the keyframe rate), or the |
65 * last received keyframe (which will cause a simple burst-on-connect). |
58 * last received keyframe (which will cause a simple burst-on-connect). |
66 * Multifdsink will always keep at least one keyframe in its internal buffers |
59 * Multifdsink will always keep at least one keyframe in its internal buffers |
67 * when the sync-mode is set to latest-keyframe. |
60 * when the sync-mode is set to latest-keyframe. |
68 * </para> |
61 * |
69 * <para> |
62 * As of version 0.10.8, there are additional values for the #GstMultiFdSink:sync-method |
70 * As of version 0.10.8, there are additional values for the sync-method |
|
71 * property to allow finer control over burst-on-connect behaviour. By selecting |
63 * property to allow finer control over burst-on-connect behaviour. By selecting |
72 * the 'burst' method a minimum burst size can be chosen, 'burst-keyframe' |
64 * the 'burst' method a minimum burst size can be chosen, 'burst-keyframe' |
73 * additionally requires that the burst begin with a keyframe, and |
65 * additionally requires that the burst begin with a keyframe, and |
74 * 'burst-with-keyframe' attempts to burst beginning with a keyframe, but will |
66 * 'burst-with-keyframe' attempts to burst beginning with a keyframe, but will |
75 * prefer a minimum burst size even if it requires not starting with a keyframe. |
67 * prefer a minimum burst size even if it requires not starting with a keyframe. |
76 * </para> |
68 * |
77 * <para> |
|
78 * Multifdsink can be instructed to keep at least a minimum amount of data |
69 * Multifdsink can be instructed to keep at least a minimum amount of data |
79 * expressed in time or byte units in its internal queues with the the |
70 * expressed in time or byte units in its internal queues with the the |
80 * "time-min" and "bytes-min" properties respectively. These properties are |
71 * #GstMultiFdSink:time-min and #GstMultiFdSink:bytes-min properties respectively. |
81 * useful if the application adds clients with the "add-full" signal to |
72 * These properties are useful if the application adds clients with the |
82 * make sure that a burst connect can actually be honored. |
73 * #GstMultiFdSink::add-full signal to make sure that a burst connect can |
83 * </para> |
74 * actually be honored. |
84 * <para> |
75 * |
85 * When streaming data, clients are allowed to read at a different rate than |
76 * When streaming data, clients are allowed to read at a different rate than |
86 * the rate at which multifdsink receives data. If the client is reading too |
77 * the rate at which multifdsink receives data. If the client is reading too |
87 * fast, no data will be send to the client until multifdsink receives more |
78 * fast, no data will be send to the client until multifdsink receives more |
88 * data. If the client, however, reads too slowly, data for that client will be |
79 * data. If the client, however, reads too slowly, data for that client will be |
89 * queued up in multifdsink. Two properties control the amount of data |
80 * queued up in multifdsink. Two properties control the amount of data |
90 * (buffers) that is queued in multifdsink: "buffers-max" and |
81 * (buffers) that is queued in multifdsink: #GstMultiFdSink:buffers-max and |
91 * "buffers-soft-max". A client that falls behind by "buffers-max" is removed |
82 * #GstMultiFdSink:buffers-soft-max. A client that falls behind by |
92 * from multifdsink forcibly. |
83 * #GstMultiFdSink:buffers-max is removed from multifdsink forcibly. |
93 * </para> |
84 * |
94 * <para> |
85 * A client with a lag of at least #GstMultiFdSink:buffers-soft-max enters the recovery |
95 * A client with a lag of at least "buffers-soft-max" enters the recovery |
86 * procedure which is controlled with the #GstMultiFdSink:recover-policy property. |
96 * procedure which is controlled with the "recover-policy" property. A recover |
87 * A recover policy of NONE will do nothing, RESYNC_LATEST will send the most recently |
97 * policy of NONE will do nothing, RESYNC_LATEST will send the most recently |
|
98 * received buffer as the next buffer for the client, RESYNC_SOFT_LIMIT |
88 * received buffer as the next buffer for the client, RESYNC_SOFT_LIMIT |
99 * positions the client to the soft limit in the buffer queue and |
89 * positions the client to the soft limit in the buffer queue and |
100 * RESYNC_KEYFRAME positions the client at the most recent keyframe in the |
90 * RESYNC_KEYFRAME positions the client at the most recent keyframe in the |
101 * buffer queue. |
91 * buffer queue. |
102 * </para> |
92 * |
103 * <para> |
|
104 * multifdsink will by default synchronize on the clock before serving the |
93 * multifdsink will by default synchronize on the clock before serving the |
105 * buffers to the clients. This behaviour can be disabled by setting the sync |
94 * buffers to the clients. This behaviour can be disabled by setting the sync |
106 * property to FALSE. Multifdsink will by default not do QoS and will never |
95 * property to FALSE. Multifdsink will by default not do QoS and will never |
107 * drop late buffers. |
96 * drop late buffers. |
108 * </para> |
|
109 * </refsect2> |
|
110 * |
97 * |
111 * Last reviewed on 2006-09-12 (0.10.10) |
98 * Last reviewed on 2006-09-12 (0.10.10) |
112 */ |
99 */ |
113 |
100 |
114 #ifdef HAVE_CONFIG_H |
101 #ifdef HAVE_CONFIG_H |
115 #include "config.h" |
102 #include "config.h" |
116 #endif |
103 #endif |
117 #include <gst/gst-i18n-plugin.h> |
104 #include <gst/gst-i18n-plugin.h> |
118 |
105 |
119 #include <sys/ioctl.h> |
106 #include <sys/ioctl.h> |
107 |
|
108 #ifdef HAVE_UNISTD_H |
|
120 #include <unistd.h> |
109 #include <unistd.h> |
110 #endif |
|
111 |
|
121 #include <fcntl.h> |
112 #include <fcntl.h> |
122 #include <sys/types.h> |
113 #include <sys/types.h> |
123 #include <sys/socket.h> |
114 #include <sys/socket.h> |
124 #include <sys/stat.h> |
115 #include <sys/stat.h> |
116 #include <netinet/in.h> |
|
117 #include <netinet/in.h> |
|
118 #include <arpa/inet.h> |
|
125 |
119 |
126 #ifdef HAVE_FIONREAD_IN_SYS_FILIO |
120 #ifdef HAVE_FIONREAD_IN_SYS_FILIO |
127 #include <sys/filio.h> |
121 #include <sys/filio.h> |
128 #endif |
122 #endif |
129 |
123 |
174 #define DEFAULT_BUFFERS_MAX -1 |
168 #define DEFAULT_BUFFERS_MAX -1 |
175 #define DEFAULT_BUFFERS_SOFT_MAX -1 |
169 #define DEFAULT_BUFFERS_SOFT_MAX -1 |
176 #define DEFAULT_TIME_MIN -1 |
170 #define DEFAULT_TIME_MIN -1 |
177 #define DEFAULT_BYTES_MIN -1 |
171 #define DEFAULT_BYTES_MIN -1 |
178 #define DEFAULT_BUFFERS_MIN -1 |
172 #define DEFAULT_BUFFERS_MIN -1 |
179 #define DEFAULT_UNIT_TYPE GST_UNIT_TYPE_BUFFERS |
173 #define DEFAULT_UNIT_TYPE GST_TCP_UNIT_TYPE_BUFFERS |
180 #define DEFAULT_UNITS_MAX -1 |
174 #define DEFAULT_UNITS_MAX -1 |
181 #define DEFAULT_UNITS_SOFT_MAX -1 |
175 #define DEFAULT_UNITS_SOFT_MAX -1 |
182 #define DEFAULT_RECOVER_POLICY GST_RECOVER_POLICY_NONE |
176 #define DEFAULT_RECOVER_POLICY GST_RECOVER_POLICY_NONE |
183 #define DEFAULT_TIMEOUT 0 |
177 #define DEFAULT_TIMEOUT 0 |
184 #define DEFAULT_SYNC_METHOD GST_SYNC_METHOD_LATEST |
178 #define DEFAULT_SYNC_METHOD GST_SYNC_METHOD_LATEST |
185 |
179 |
186 #define DEFAULT_BURST_UNIT GST_UNIT_TYPE_UNDEFINED |
180 #define DEFAULT_BURST_UNIT GST_TCP_UNIT_TYPE_UNDEFINED |
187 #define DEFAULT_BURST_VALUE 0 |
181 #define DEFAULT_BURST_VALUE 0 |
182 |
|
183 #define DEFAULT_QOS_DSCP -1 |
|
184 #define DEFAULT_HANDLE_READ TRUE |
|
185 |
|
186 #define DEFAULT_RESEND_STREAMHEADER TRUE |
|
188 |
187 |
189 enum |
188 enum |
190 { |
189 { |
191 PROP_0, |
190 PROP_0, |
192 PROP_PROTOCOL, |
191 PROP_PROTOCOL, |
212 PROP_BYTES_TO_SERVE, |
211 PROP_BYTES_TO_SERVE, |
213 PROP_BYTES_SERVED, |
212 PROP_BYTES_SERVED, |
214 |
213 |
215 PROP_BURST_UNIT, |
214 PROP_BURST_UNIT, |
216 PROP_BURST_VALUE, |
215 PROP_BURST_VALUE, |
216 |
|
217 PROP_QOS_DSCP, |
|
218 |
|
219 PROP_HANDLE_READ, |
|
220 |
|
221 PROP_RESEND_STREAMHEADER, |
|
222 |
|
223 PROP_NUM_FDS, |
|
224 |
|
225 PROP_LAST |
|
217 }; |
226 }; |
218 |
227 |
219 /* For backward compat, we can't really select the poll mode anymore with |
228 /* For backward compat, we can't really select the poll mode anymore with |
220 * GstPoll. */ |
229 * GstPoll. */ |
221 #define GST_TYPE_FDSET_MODE (gst_fdset_mode_get_type()) |
230 #define GST_TYPE_FDSET_MODE (gst_fdset_mode_get_type()) |
227 {0, "Select", "select"}, |
236 {0, "Select", "select"}, |
228 {1, "Poll", "poll"}, |
237 {1, "Poll", "poll"}, |
229 {2, "EPoll", "epoll"}, |
238 {2, "EPoll", "epoll"}, |
230 {0, NULL, NULL}, |
239 {0, NULL, NULL}, |
231 }; |
240 }; |
241 |
|
232 if (!fdset_mode_type) { |
242 if (!fdset_mode_type) { |
233 fdset_mode_type = g_enum_register_static ("GstFDSetMode", fdset_mode); |
243 fdset_mode_type = g_enum_register_static ("GstFDSetMode", fdset_mode); |
234 } |
244 } |
235 return fdset_mode_type; |
245 return fdset_mode_type; |
236 } |
246 } |
292 static GType |
302 static GType |
293 gst_unit_type_get_type (void) |
303 gst_unit_type_get_type (void) |
294 { |
304 { |
295 static GType unit_type_type = 0; |
305 static GType unit_type_type = 0; |
296 static const GEnumValue unit_type[] = { |
306 static const GEnumValue unit_type[] = { |
297 {GST_UNIT_TYPE_UNDEFINED, "Undefined", "undefined"}, |
307 {GST_TCP_UNIT_TYPE_UNDEFINED, "Undefined", "undefined"}, |
298 {GST_UNIT_TYPE_BUFFERS, "Buffers", "buffers"}, |
308 {GST_TCP_UNIT_TYPE_BUFFERS, "Buffers", "buffers"}, |
299 {GST_UNIT_TYPE_BYTES, "Bytes", "bytes"}, |
309 {GST_TCP_UNIT_TYPE_BYTES, "Bytes", "bytes"}, |
300 {GST_UNIT_TYPE_TIME, "Time", "time"}, |
310 {GST_TCP_UNIT_TYPE_TIME, "Time", "time"}, |
301 {0, NULL, NULL}, |
311 {0, NULL, NULL}, |
302 }; |
312 }; |
303 |
313 |
304 if (!unit_type_type) { |
314 if (!unit_type_type) { |
305 unit_type_type = g_enum_register_static ("GstTCPUnitType", unit_type); |
315 unit_type_type = g_enum_register_static ("GstTCPUnitType", unit_type); |
376 gobject_class->get_property = gst_multi_fd_sink_get_property; |
386 gobject_class->get_property = gst_multi_fd_sink_get_property; |
377 gobject_class->finalize = gst_multi_fd_sink_finalize; |
387 gobject_class->finalize = gst_multi_fd_sink_finalize; |
378 |
388 |
379 g_object_class_install_property (gobject_class, PROP_PROTOCOL, |
389 g_object_class_install_property (gobject_class, PROP_PROTOCOL, |
380 g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in", |
390 g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in", |
381 GST_TYPE_TCP_PROTOCOL, DEFAULT_PROTOCOL, G_PARAM_READWRITE)); |
391 GST_TYPE_TCP_PROTOCOL, DEFAULT_PROTOCOL, |
392 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
382 |
393 |
383 /** |
394 /** |
384 * GstMultiFdSink::mode |
395 * GstMultiFdSink::mode |
385 * |
396 * |
386 * The mode for selecting activity on the fds. |
397 * The mode for selecting activity on the fds. |
389 * select and use the most optimal method. |
400 * select and use the most optimal method. |
390 */ |
401 */ |
391 g_object_class_install_property (gobject_class, PROP_MODE, |
402 g_object_class_install_property (gobject_class, PROP_MODE, |
392 g_param_spec_enum ("mode", "Mode", |
403 g_param_spec_enum ("mode", "Mode", |
393 "The mode for selecting activity on the fds (deprecated)", |
404 "The mode for selecting activity on the fds (deprecated)", |
394 GST_TYPE_FDSET_MODE, DEFAULT_MODE, G_PARAM_READWRITE)); |
405 GST_TYPE_FDSET_MODE, DEFAULT_MODE, |
406 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
395 |
407 |
396 g_object_class_install_property (gobject_class, PROP_BUFFERS_MAX, |
408 g_object_class_install_property (gobject_class, PROP_BUFFERS_MAX, |
397 g_param_spec_int ("buffers-max", "Buffers max", |
409 g_param_spec_int ("buffers-max", "Buffers max", |
398 "max number of buffers to queue for a client (-1 = no limit)", -1, |
410 "max number of buffers to queue for a client (-1 = no limit)", -1, |
399 G_MAXINT, DEFAULT_BUFFERS_MAX, G_PARAM_READWRITE)); |
411 G_MAXINT, DEFAULT_BUFFERS_MAX, |
400 g_object_class_install_property (gobject_class, |
412 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
401 PROP_BUFFERS_SOFT_MAX, g_param_spec_int ("buffers-soft-max", |
413 g_object_class_install_property (gobject_class, PROP_BUFFERS_SOFT_MAX, |
402 "Buffers soft max", |
414 g_param_spec_int ("buffers-soft-max", "Buffers soft max", |
403 "Recover client when going over this limit (-1 = no limit)", -1, |
415 "Recover client when going over this limit (-1 = no limit)", -1, |
404 G_MAXINT, DEFAULT_BUFFERS_SOFT_MAX, G_PARAM_READWRITE)); |
416 G_MAXINT, DEFAULT_BUFFERS_SOFT_MAX, |
417 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
405 |
418 |
406 g_object_class_install_property (gobject_class, PROP_BYTES_MIN, |
419 g_object_class_install_property (gobject_class, PROP_BYTES_MIN, |
407 g_param_spec_int ("bytes-min", "Bytes min", |
420 g_param_spec_int ("bytes-min", "Bytes min", |
408 "min number of bytes to queue (-1 = as little as possible)", -1, |
421 "min number of bytes to queue (-1 = as little as possible)", -1, |
409 G_MAXINT, DEFAULT_BYTES_MIN, G_PARAM_READWRITE)); |
422 G_MAXINT, DEFAULT_BYTES_MIN, |
423 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
410 g_object_class_install_property (gobject_class, PROP_TIME_MIN, |
424 g_object_class_install_property (gobject_class, PROP_TIME_MIN, |
411 g_param_spec_int64 ("time-min", "Time min", |
425 g_param_spec_int64 ("time-min", "Time min", |
412 "min number of time to queue (-1 = as little as possible)", -1, |
426 "min number of time to queue (-1 = as little as possible)", -1, |
413 G_MAXINT64, DEFAULT_TIME_MIN, G_PARAM_READWRITE)); |
427 G_MAXINT64, DEFAULT_TIME_MIN, |
428 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
414 g_object_class_install_property (gobject_class, PROP_BUFFERS_MIN, |
429 g_object_class_install_property (gobject_class, PROP_BUFFERS_MIN, |
415 g_param_spec_int ("buffers-min", "Buffers min", |
430 g_param_spec_int ("buffers-min", "Buffers min", |
416 "min number of buffers to queue (-1 = as few as possible)", -1, |
431 "min number of buffers to queue (-1 = as few as possible)", -1, |
417 G_MAXINT, DEFAULT_BUFFERS_MIN, G_PARAM_READWRITE)); |
432 G_MAXINT, DEFAULT_BUFFERS_MIN, |
433 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
418 |
434 |
419 g_object_class_install_property (gobject_class, PROP_UNIT_TYPE, |
435 g_object_class_install_property (gobject_class, PROP_UNIT_TYPE, |
420 g_param_spec_enum ("unit-type", "Units type", |
436 g_param_spec_enum ("unit-type", "Units type", |
421 "The unit to measure the max/soft-max/queued properties", |
437 "The unit to measure the max/soft-max/queued properties", |
422 GST_TYPE_UNIT_TYPE, DEFAULT_UNIT_TYPE, G_PARAM_READWRITE)); |
438 GST_TYPE_UNIT_TYPE, DEFAULT_UNIT_TYPE, |
439 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
423 g_object_class_install_property (gobject_class, PROP_UNITS_MAX, |
440 g_object_class_install_property (gobject_class, PROP_UNITS_MAX, |
424 g_param_spec_int64 ("units-max", "Units max", |
441 g_param_spec_int64 ("units-max", "Units max", |
425 "max number of units to queue (-1 = no limit)", -1, G_MAXINT64, |
442 "max number of units to queue (-1 = no limit)", -1, G_MAXINT64, |
426 DEFAULT_UNITS_MAX, G_PARAM_READWRITE)); |
443 DEFAULT_UNITS_MAX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
427 g_object_class_install_property (gobject_class, PROP_UNITS_SOFT_MAX, |
444 g_object_class_install_property (gobject_class, PROP_UNITS_SOFT_MAX, |
428 g_param_spec_int64 ("units-soft-max", "Units soft max", |
445 g_param_spec_int64 ("units-soft-max", "Units soft max", |
429 "Recover client when going over this limit (-1 = no limit)", -1, |
446 "Recover client when going over this limit (-1 = no limit)", -1, |
430 G_MAXINT64, DEFAULT_UNITS_SOFT_MAX, G_PARAM_READWRITE)); |
447 G_MAXINT64, DEFAULT_UNITS_SOFT_MAX, |
448 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
431 |
449 |
432 g_object_class_install_property (gobject_class, PROP_BUFFERS_QUEUED, |
450 g_object_class_install_property (gobject_class, PROP_BUFFERS_QUEUED, |
433 g_param_spec_uint ("buffers-queued", "Buffers queued", |
451 g_param_spec_uint ("buffers-queued", "Buffers queued", |
434 "Number of buffers currently queued", 0, G_MAXUINT, 0, |
452 "Number of buffers currently queued", 0, G_MAXUINT, 0, |
435 G_PARAM_READABLE)); |
453 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
436 #if NOT_IMPLEMENTED |
454 #if NOT_IMPLEMENTED |
437 g_object_class_install_property (gobject_class, PROP_BYTES_QUEUED, |
455 g_object_class_install_property (gobject_class, PROP_BYTES_QUEUED, |
438 g_param_spec_uint ("bytes-queued", "Bytes queued", |
456 g_param_spec_uint ("bytes-queued", "Bytes queued", |
439 "Number of bytes currently queued", 0, G_MAXUINT, 0, |
457 "Number of bytes currently queued", 0, G_MAXUINT, 0, |
440 G_PARAM_READABLE)); |
458 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
441 g_object_class_install_property (gobject_class, PROP_TIME_QUEUED, |
459 g_object_class_install_property (gobject_class, PROP_TIME_QUEUED, |
442 g_param_spec_uint64 ("time-queued", "Time queued", |
460 g_param_spec_uint64 ("time-queued", "Time queued", |
443 "Number of time currently queued", 0, G_MAXUINT64, 0, |
461 "Number of time currently queued", 0, G_MAXUINT64, 0, |
444 G_PARAM_READABLE)); |
462 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
445 #endif |
463 #endif |
446 |
464 |
447 g_object_class_install_property (gobject_class, PROP_RECOVER_POLICY, |
465 g_object_class_install_property (gobject_class, PROP_RECOVER_POLICY, |
448 g_param_spec_enum ("recover-policy", "Recover Policy", |
466 g_param_spec_enum ("recover-policy", "Recover Policy", |
449 "How to recover when client reaches the soft max", |
467 "How to recover when client reaches the soft max", |
450 GST_TYPE_RECOVER_POLICY, DEFAULT_RECOVER_POLICY, G_PARAM_READWRITE)); |
468 GST_TYPE_RECOVER_POLICY, DEFAULT_RECOVER_POLICY, |
469 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
451 g_object_class_install_property (gobject_class, PROP_TIMEOUT, |
470 g_object_class_install_property (gobject_class, PROP_TIMEOUT, |
452 g_param_spec_uint64 ("timeout", "Timeout", |
471 g_param_spec_uint64 ("timeout", "Timeout", |
453 "Maximum inactivity timeout in nanoseconds for a client (0 = no limit)", |
472 "Maximum inactivity timeout in nanoseconds for a client (0 = no limit)", |
454 0, G_MAXUINT64, DEFAULT_TIMEOUT, G_PARAM_READWRITE)); |
473 0, G_MAXUINT64, DEFAULT_TIMEOUT, |
474 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
455 g_object_class_install_property (gobject_class, PROP_SYNC_METHOD, |
475 g_object_class_install_property (gobject_class, PROP_SYNC_METHOD, |
456 g_param_spec_enum ("sync-method", "Sync Method", |
476 g_param_spec_enum ("sync-method", "Sync Method", |
457 "How to sync new clients to the stream", |
477 "How to sync new clients to the stream", GST_TYPE_SYNC_METHOD, |
458 GST_TYPE_SYNC_METHOD, DEFAULT_SYNC_METHOD, G_PARAM_READWRITE)); |
478 DEFAULT_SYNC_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
459 g_object_class_install_property (gobject_class, PROP_BYTES_TO_SERVE, |
479 g_object_class_install_property (gobject_class, PROP_BYTES_TO_SERVE, |
460 g_param_spec_uint64 ("bytes-to-serve", "Bytes to serve", |
480 g_param_spec_uint64 ("bytes-to-serve", "Bytes to serve", |
461 "Number of bytes received to serve to clients", 0, G_MAXUINT64, 0, |
481 "Number of bytes received to serve to clients", 0, G_MAXUINT64, 0, |
462 G_PARAM_READABLE)); |
482 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
463 g_object_class_install_property (gobject_class, PROP_BYTES_SERVED, |
483 g_object_class_install_property (gobject_class, PROP_BYTES_SERVED, |
464 g_param_spec_uint64 ("bytes-served", "Bytes served", |
484 g_param_spec_uint64 ("bytes-served", "Bytes served", |
465 "Total number of bytes send to all clients", 0, G_MAXUINT64, 0, |
485 "Total number of bytes send to all clients", 0, G_MAXUINT64, 0, |
466 G_PARAM_READABLE)); |
486 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
467 |
487 |
468 g_object_class_install_property (gobject_class, PROP_BURST_UNIT, |
488 g_object_class_install_property (gobject_class, PROP_BURST_UNIT, |
469 g_param_spec_enum ("burst-unit", "Burst unit", |
489 g_param_spec_enum ("burst-unit", "Burst unit", |
470 "The format of the burst units (when sync-method is burst[[-with]-keyframe])", |
490 "The format of the burst units (when sync-method is burst[[-with]-keyframe])", |
471 GST_TYPE_UNIT_TYPE, DEFAULT_BURST_UNIT, G_PARAM_READWRITE)); |
491 GST_TYPE_UNIT_TYPE, DEFAULT_BURST_UNIT, |
492 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
472 g_object_class_install_property (gobject_class, PROP_BURST_VALUE, |
493 g_object_class_install_property (gobject_class, PROP_BURST_VALUE, |
473 g_param_spec_uint64 ("burst-value", "Burst value", |
494 g_param_spec_uint64 ("burst-value", "Burst value", |
474 "The amount of burst expressed in burst-unit", |
495 "The amount of burst expressed in burst-unit", 0, G_MAXUINT64, |
475 0, G_MAXUINT64, DEFAULT_BURST_VALUE, G_PARAM_READWRITE)); |
496 DEFAULT_BURST_VALUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
497 |
|
498 g_object_class_install_property (gobject_class, PROP_QOS_DSCP, |
|
499 g_param_spec_int ("qos-dscp", "QoS diff srv code point", |
|
500 "Quality of Service, differentiated services code point (-1 default)", |
|
501 -1, 63, DEFAULT_QOS_DSCP, |
|
502 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
503 /** |
|
504 * GstMultiFdSink::handle-read |
|
505 * |
|
506 * Handle read requests from clients and discard the data. |
|
507 * |
|
508 * Since: 0.10.23 |
|
509 */ |
|
510 g_object_class_install_property (gobject_class, PROP_HANDLE_READ, |
|
511 g_param_spec_boolean ("handle-read", "Handle Read", |
|
512 "Handle client reads and discard the data", |
|
513 DEFAULT_HANDLE_READ, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
514 /** |
|
515 * GstMultiFdSink::resend-streamheader |
|
516 * |
|
517 * Resend the streamheaders to existing clients when they change. |
|
518 * |
|
519 * Since: 0.10.23 |
|
520 */ |
|
521 g_object_class_install_property (gobject_class, PROP_RESEND_STREAMHEADER, |
|
522 g_param_spec_boolean ("resend-streamheader", "Resend streamheader", |
|
523 "Resend the streamheader if it changes in the caps", |
|
524 DEFAULT_RESEND_STREAMHEADER, |
|
525 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
526 |
|
527 g_object_class_install_property (gobject_class, PROP_NUM_FDS, |
|
528 g_param_spec_uint ("num-fds", "Number of fds", |
|
529 "The current number of client file descriptors.", |
|
530 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
|
476 |
531 |
477 /** |
532 /** |
478 * GstMultiFdSink::add: |
533 * GstMultiFdSink::add: |
479 * @gstmultifdsink: the multifdsink element to emit this signal on |
534 * @gstmultifdsink: the multifdsink element to emit this signal on |
480 * @fd: the file descriptor to add to multifdsink |
535 * @fd: the file descriptor to add to multifdsink |
488 G_TYPE_INT); |
543 G_TYPE_INT); |
489 /** |
544 /** |
490 * GstMultiFdSink::add-full: |
545 * GstMultiFdSink::add-full: |
491 * @gstmultifdsink: the multifdsink element to emit this signal on |
546 * @gstmultifdsink: the multifdsink element to emit this signal on |
492 * @fd: the file descriptor to add to multifdsink |
547 * @fd: the file descriptor to add to multifdsink |
493 * @keyframe: start bursting from a keyframe |
548 * @sync: the sync method to use |
494 * @unit_type_min: the unit-type of @value_min |
549 * @unit_type_min: the unit-type of @value_min |
495 * @value_min: the minimum amount of data to burst expressed in |
550 * @value_min: the minimum amount of data to burst expressed in |
496 * @unit_type_min units. |
551 * @unit_type_min units. |
497 * @unit_type_max: the unit-type of @value_max |
552 * @unit_type_max: the unit-type of @value_max |
498 * @value_max: the maximum amount of data to burst expressed in |
553 * @value_max: the maximum amount of data to burst expressed in |
503 */ |
558 */ |
504 gst_multi_fd_sink_signals[SIGNAL_ADD_BURST] = |
559 gst_multi_fd_sink_signals[SIGNAL_ADD_BURST] = |
505 g_signal_new ("add-full", G_TYPE_FROM_CLASS (klass), |
560 g_signal_new ("add-full", G_TYPE_FROM_CLASS (klass), |
506 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstMultiFdSinkClass, |
561 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstMultiFdSinkClass, |
507 add_full), NULL, NULL, |
562 add_full), NULL, NULL, |
508 gst_tcp_marshal_VOID__INT_BOOLEAN_INT_UINT64_INT_UINT64, G_TYPE_NONE, 6, |
563 gst_tcp_marshal_VOID__INT_ENUM_INT_UINT64_INT_UINT64, G_TYPE_NONE, 6, |
509 G_TYPE_INT, G_TYPE_BOOLEAN, GST_TYPE_UNIT_TYPE, G_TYPE_UINT64, |
564 G_TYPE_INT, GST_TYPE_SYNC_METHOD, GST_TYPE_UNIT_TYPE, G_TYPE_UINT64, |
510 GST_TYPE_UNIT_TYPE, G_TYPE_UINT64); |
565 GST_TYPE_UNIT_TYPE, G_TYPE_UINT64); |
511 /** |
566 /** |
512 * GstMultiFdSink::remove: |
567 * GstMultiFdSink::remove: |
513 * @gstmultifdsink: the multifdsink element to emit this signal on |
568 * @gstmultifdsink: the multifdsink element to emit this signal on |
514 * @fd: the file descriptor to remove from multifdsink |
569 * @fd: the file descriptor to remove from multifdsink |
519 g_signal_new ("remove", G_TYPE_FROM_CLASS (klass), |
574 g_signal_new ("remove", G_TYPE_FROM_CLASS (klass), |
520 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstMultiFdSinkClass, |
575 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstMultiFdSinkClass, |
521 remove), NULL, NULL, gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1, |
576 remove), NULL, NULL, gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1, |
522 G_TYPE_INT); |
577 G_TYPE_INT); |
523 /** |
578 /** |
524 * GstMultiFdSink::remove_flush: |
579 * GstMultiFdSink::remove-flush: |
525 * @gstmultifdsink: the multifdsink element to emit this signal on |
580 * @gstmultifdsink: the multifdsink element to emit this signal on |
526 * @fd: the file descriptor to remove from multifdsink |
581 * @fd: the file descriptor to remove from multifdsink |
527 * |
582 * |
528 * Remove the given open file descriptor from multifdsink after flushing all |
583 * Remove the given open file descriptor from multifdsink after flushing all |
529 * the pending data to the fd. |
584 * the pending data to the fd. |
660 this->timeout = DEFAULT_TIMEOUT; |
715 this->timeout = DEFAULT_TIMEOUT; |
661 this->def_sync_method = DEFAULT_SYNC_METHOD; |
716 this->def_sync_method = DEFAULT_SYNC_METHOD; |
662 this->def_burst_unit = DEFAULT_BURST_UNIT; |
717 this->def_burst_unit = DEFAULT_BURST_UNIT; |
663 this->def_burst_value = DEFAULT_BURST_VALUE; |
718 this->def_burst_value = DEFAULT_BURST_VALUE; |
664 |
719 |
720 this->qos_dscp = DEFAULT_QOS_DSCP; |
|
721 this->handle_read = DEFAULT_HANDLE_READ; |
|
722 |
|
723 this->resend_streamheader = DEFAULT_RESEND_STREAMHEADER; |
|
724 |
|
665 this->header_flags = 0; |
725 this->header_flags = 0; |
666 } |
726 } |
667 |
727 |
668 static void |
728 static void |
669 gst_multi_fd_sink_finalize (GObject * object) |
729 gst_multi_fd_sink_finalize (GObject * object) |
675 CLIENTS_LOCK_FREE (this); |
735 CLIENTS_LOCK_FREE (this); |
676 g_hash_table_destroy (this->fd_hash); |
736 g_hash_table_destroy (this->fd_hash); |
677 g_array_free (this->bufqueue, TRUE); |
737 g_array_free (this->bufqueue, TRUE); |
678 |
738 |
679 G_OBJECT_CLASS (parent_class)->finalize (object); |
739 G_OBJECT_CLASS (parent_class)->finalize (object); |
740 } |
|
741 |
|
742 static gint |
|
743 setup_dscp_client (GstMultiFdSink * sink, GstTCPClient * client) |
|
744 { |
|
745 gint tos; |
|
746 gint ret; |
|
747 union gst_sockaddr |
|
748 { |
|
749 struct sockaddr sa; |
|
750 struct sockaddr_in6 sa_in6; |
|
751 struct sockaddr_storage sa_stor; |
|
752 } sa; |
|
753 socklen_t slen = sizeof (sa); |
|
754 gint af; |
|
755 |
|
756 /* don't touch */ |
|
757 if (sink->qos_dscp < 0) |
|
758 return 0; |
|
759 |
|
760 if ((ret = getsockname (client->fd.fd, &sa.sa, &slen)) < 0) { |
|
761 GST_DEBUG_OBJECT (sink, "could not get sockname: %s", g_strerror (errno)); |
|
762 return ret; |
|
763 } |
|
764 |
|
765 af = sa.sa.sa_family; |
|
766 |
|
767 /* if this is an IPv4-mapped address then do IPv4 QoS */ |
|
768 if (af == AF_INET6) { |
|
769 |
|
770 GST_DEBUG_OBJECT (sink, "check IP6 socket"); |
|
771 if (IN6_IS_ADDR_V4MAPPED (&(sa.sa_in6.sin6_addr))) { |
|
772 GST_DEBUG_OBJECT (sink, "mapped to IPV4"); |
|
773 af = AF_INET; |
|
774 } |
|
775 } |
|
776 |
|
777 /* extract and shift 6 bits of the DSCP */ |
|
778 tos = (sink->qos_dscp & 0x3f) << 2; |
|
779 |
|
780 switch (af) { |
|
781 case AF_INET: |
|
782 ret = setsockopt (client->fd.fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)); |
|
783 break; |
|
784 case AF_INET6: |
|
785 #ifdef IPV6_TCLASS |
|
786 ret = |
|
787 setsockopt (client->fd.fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, |
|
788 sizeof (tos)); |
|
789 break; |
|
790 #endif |
|
791 default: |
|
792 ret = 0; |
|
793 GST_ERROR_OBJECT (sink, "unsupported AF"); |
|
794 break; |
|
795 } |
|
796 if (ret) |
|
797 GST_DEBUG_OBJECT (sink, "could not set DSCP: %s", g_strerror (errno)); |
|
798 |
|
799 return ret; |
|
800 } |
|
801 |
|
802 |
|
803 static void |
|
804 setup_dscp (GstMultiFdSink * sink) |
|
805 { |
|
806 GList *clients, *next; |
|
807 |
|
808 CLIENTS_LOCK (sink); |
|
809 for (clients = sink->clients; clients; clients = next) { |
|
810 GstTCPClient *client; |
|
811 |
|
812 client = (GstTCPClient *) clients->data; |
|
813 next = g_list_next (clients); |
|
814 |
|
815 setup_dscp_client (sink, client); |
|
816 } |
|
817 CLIENTS_UNLOCK (sink); |
|
680 } |
818 } |
681 |
819 |
682 /* "add-full" signal implementation */ |
820 /* "add-full" signal implementation */ |
683 #ifdef __SYMBIAN32__ |
821 #ifdef __SYMBIAN32__ |
684 EXPORT_C |
822 EXPORT_C |
685 #endif |
823 #endif |
686 |
824 |
687 void |
825 void |
688 gst_multi_fd_sink_add_full (GstMultiFdSink * sink, int fd, |
826 gst_multi_fd_sink_add_full (GstMultiFdSink * sink, int fd, |
689 GstSyncMethod sync_method, GstUnitType min_unit, guint64 min_value, |
827 GstSyncMethod sync_method, GstTCPUnitType min_unit, guint64 min_value, |
690 GstUnitType max_unit, guint64 max_value) |
828 GstTCPUnitType max_unit, guint64 max_value) |
691 { |
829 { |
692 GstTCPClient *client; |
830 GstTCPClient *client; |
693 GList *clink; |
831 GList *clink; |
694 GTimeVal now; |
832 GTimeVal now; |
695 gint flags, res; |
833 gint flags, res; |
743 clink = sink->clients = g_list_prepend (sink->clients, client); |
881 clink = sink->clients = g_list_prepend (sink->clients, client); |
744 g_hash_table_insert (sink->fd_hash, &client->fd.fd, clink); |
882 g_hash_table_insert (sink->fd_hash, &client->fd.fd, clink); |
745 sink->clients_cookie++; |
883 sink->clients_cookie++; |
746 |
884 |
747 /* set the socket to non blocking */ |
885 /* set the socket to non blocking */ |
748 //temporary commented for multifdsink issue |
886 // temporary fix for multifdsink |
749 //res = fcntl (fd, F_SETFL, O_NONBLOCK); //Arun |
887 //res = fcntl (fd, F_SETFL, O_NONBLOCK); |
750 |
|
751 /* we always read from a client */ |
888 /* we always read from a client */ |
752 gst_poll_add_fd (sink->fdset, &client->fd); |
889 gst_poll_add_fd (sink->fdset, &client->fd); |
753 |
890 |
754 /* we don't try to read from write only fds */ |
891 /* we don't try to read from write only fds */ |
755 flags = fcntl (fd, F_GETFL, 0); |
892 if (sink->handle_read) { |
756 if ((flags & O_ACCMODE) != O_WRONLY) { |
893 flags = fcntl (fd, F_GETFL, 0); |
757 gst_poll_fd_ctl_read (sink->fdset, &client->fd, TRUE); |
894 if ((flags & O_ACCMODE) != O_WRONLY) { |
895 gst_poll_fd_ctl_read (sink->fdset, &client->fd, TRUE); |
|
896 } |
|
758 } |
897 } |
759 /* figure out the mode, can't use send() for non sockets */ |
898 /* figure out the mode, can't use send() for non sockets */ |
760 res = fstat (fd, &statbuf); |
899 res = fstat (fd, &statbuf); |
761 if (S_ISSOCK (statbuf.st_mode)) { |
900 if (S_ISSOCK (statbuf.st_mode)) { |
762 client->is_socket = TRUE; |
901 client->is_socket = TRUE; |
902 setup_dscp_client (sink, client); |
|
763 } |
903 } |
764 |
904 |
765 gst_poll_restart (sink->fdset); |
905 gst_poll_restart (sink->fdset); |
766 |
906 |
767 CLIENTS_UNLOCK (sink); |
907 CLIENTS_UNLOCK (sink); |
1277 "[fd %5d] previous caps did not have streamheader, sending", |
1417 "[fd %5d] previous caps did not have streamheader, sending", |
1278 client->fd.fd); |
1418 client->fd.fd); |
1279 send_streamheader = TRUE; |
1419 send_streamheader = TRUE; |
1280 } else { |
1420 } else { |
1281 /* both old and new caps have streamheader set */ |
1421 /* both old and new caps have streamheader set */ |
1282 sh1 = gst_structure_get_value (s, "streamheader"); |
1422 if (!sink->resend_streamheader) { |
1283 s = gst_caps_get_structure (caps, 0); |
|
1284 sh2 = gst_structure_get_value (s, "streamheader"); |
|
1285 if (gst_value_compare (sh1, sh2) != GST_VALUE_EQUAL) { |
|
1286 GST_DEBUG_OBJECT (sink, |
1423 GST_DEBUG_OBJECT (sink, |
1287 "[fd %5d] new streamheader different from old, sending", |
1424 "[fd %5d] asked to not resend the streamheader, not sending", |
1288 client->fd.fd); |
1425 client->fd.fd); |
1289 send_streamheader = TRUE; |
1426 send_streamheader = FALSE; |
1427 } else { |
|
1428 sh1 = gst_structure_get_value (s, "streamheader"); |
|
1429 s = gst_caps_get_structure (caps, 0); |
|
1430 sh2 = gst_structure_get_value (s, "streamheader"); |
|
1431 if (gst_value_compare (sh1, sh2) != GST_VALUE_EQUAL) { |
|
1432 GST_DEBUG_OBJECT (sink, |
|
1433 "[fd %5d] new streamheader different from old, sending", |
|
1434 client->fd.fd); |
|
1435 send_streamheader = TRUE; |
|
1436 } |
|
1290 } |
1437 } |
1291 } |
1438 } |
1292 } |
1439 } |
1293 } |
1440 } |
1294 /* Replace the old caps */ |
1441 /* Replace the old caps */ |
1412 * queue to satify the limit, return len(queue) + 1 */ |
1559 * queue to satify the limit, return len(queue) + 1 */ |
1413 static gint |
1560 static gint |
1414 get_buffers_max (GstMultiFdSink * sink, gint64 max) |
1561 get_buffers_max (GstMultiFdSink * sink, gint64 max) |
1415 { |
1562 { |
1416 switch (sink->unit_type) { |
1563 switch (sink->unit_type) { |
1417 case GST_UNIT_TYPE_BUFFERS: |
1564 case GST_TCP_UNIT_TYPE_BUFFERS: |
1418 return max; |
1565 return max; |
1419 case GST_UNIT_TYPE_TIME: |
1566 case GST_TCP_UNIT_TYPE_TIME: |
1420 { |
1567 { |
1421 GstBuffer *buf; |
1568 GstBuffer *buf; |
1422 int i; |
1569 int i; |
1423 int len; |
1570 int len; |
1424 gint64 diff; |
1571 gint64 diff; |
1438 return i + 1; |
1585 return i + 1; |
1439 } |
1586 } |
1440 } |
1587 } |
1441 return len + 1; |
1588 return len + 1; |
1442 } |
1589 } |
1443 case GST_UNIT_TYPE_BYTES: |
1590 case GST_TCP_UNIT_TYPE_BYTES: |
1444 { |
1591 { |
1445 GstBuffer *buf; |
1592 GstBuffer *buf; |
1446 int i; |
1593 int i; |
1447 int len; |
1594 int len; |
1448 gint acc = 0; |
1595 gint acc = 0; |
1581 * right type, leave the other values untouched |
1728 * right type, leave the other values untouched |
1582 * |
1729 * |
1583 * Returns: FALSE if the unit is unknown or undefined. TRUE otherwise. |
1730 * Returns: FALSE if the unit is unknown or undefined. TRUE otherwise. |
1584 */ |
1731 */ |
1585 static gboolean |
1732 static gboolean |
1586 assign_value (GstUnitType unit, guint64 value, gint * bytes, gint * buffers, |
1733 assign_value (GstTCPUnitType unit, guint64 value, gint * bytes, gint * buffers, |
1587 GstClockTime * time) |
1734 GstClockTime * time) |
1588 { |
1735 { |
1589 gboolean res = TRUE; |
1736 gboolean res = TRUE; |
1590 |
1737 |
1591 /* set only the limit of the given format to the given value */ |
1738 /* set only the limit of the given format to the given value */ |
1592 switch (unit) { |
1739 switch (unit) { |
1593 case GST_UNIT_TYPE_BUFFERS: |
1740 case GST_TCP_UNIT_TYPE_BUFFERS: |
1594 *buffers = (gint) value; |
1741 *buffers = (gint) value; |
1595 break; |
1742 break; |
1596 case GST_UNIT_TYPE_TIME: |
1743 case GST_TCP_UNIT_TYPE_TIME: |
1597 *time = value; |
1744 *time = value; |
1598 break; |
1745 break; |
1599 case GST_UNIT_TYPE_BYTES: |
1746 case GST_TCP_UNIT_TYPE_BYTES: |
1600 *bytes = (gint) value; |
1747 *bytes = (gint) value; |
1601 break; |
1748 break; |
1602 case GST_UNIT_TYPE_UNDEFINED: |
1749 case GST_TCP_UNIT_TYPE_UNDEFINED: |
1603 default: |
1750 default: |
1604 res = FALSE; |
1751 res = FALSE; |
1605 break; |
1752 break; |
1606 } |
1753 } |
1607 return res; |
1754 return res; |
1614 * burst values. @idx contains the index in the buffer that contains enough |
1761 * burst values. @idx contains the index in the buffer that contains enough |
1615 * data to satisfy the limits or the last buffer in the queue when the |
1762 * data to satisfy the limits or the last buffer in the queue when the |
1616 * function returns FALSE. |
1763 * function returns FALSE. |
1617 */ |
1764 */ |
1618 static gboolean |
1765 static gboolean |
1619 count_burst_unit (GstMultiFdSink * sink, gint * min_idx, GstUnitType min_unit, |
1766 count_burst_unit (GstMultiFdSink * sink, gint * min_idx, |
1620 guint64 min_value, gint * max_idx, GstUnitType max_unit, guint64 max_value) |
1767 GstTCPUnitType min_unit, guint64 min_value, gint * max_idx, |
1768 GstTCPUnitType max_unit, guint64 max_value) |
|
1621 { |
1769 { |
1622 gint bytes_min = -1, buffers_min = -1; |
1770 gint bytes_min = -1, buffers_min = -1; |
1623 gint bytes_max = -1, buffers_max = -1; |
1771 gint bytes_max = -1, buffers_max = -1; |
1624 GstClockTime time_min = GST_CLOCK_TIME_NONE, time_max = GST_CLOCK_TIME_NONE; |
1772 GstClockTime time_min = GST_CLOCK_TIME_NONE, time_max = GST_CLOCK_TIME_NONE; |
1625 |
1773 |
2236 /* no point in searching beyond the queue length */ |
2384 /* no point in searching beyond the queue length */ |
2237 gint limit = queuelen; |
2385 gint limit = queuelen; |
2238 GstBuffer *buf; |
2386 GstBuffer *buf; |
2239 |
2387 |
2240 /* no point in searching beyond the soft-max if any. */ |
2388 /* no point in searching beyond the soft-max if any. */ |
2241 if (soft_max_buffers) { |
2389 if (soft_max_buffers > 0) { |
2242 limit = MIN (limit, soft_max_buffers); |
2390 limit = MIN (limit, soft_max_buffers); |
2243 } |
2391 } |
2244 GST_LOG_OBJECT (sink, "extending queue to include sync point, now at %d", |
2392 GST_LOG_OBJECT (sink, |
2245 max_buffer_usage); |
2393 "extending queue to include sync point, now at %d, limit is %d", |
2394 max_buffer_usage, limit); |
|
2246 for (i = 0; i < limit; i++) { |
2395 for (i = 0; i < limit; i++) { |
2247 buf = g_array_index (sink->bufqueue, GstBuffer *, i); |
2396 buf = g_array_index (sink->bufqueue, GstBuffer *, i); |
2248 if (is_sync_frame (sink, buf)) { |
2397 if (is_sync_frame (sink, buf)) { |
2249 /* found a sync frame, now extend the buffer usage to |
2398 /* found a sync frame, now extend the buffer usage to |
2250 * include at least this frame. */ |
2399 * include at least this frame. */ |
2340 if (res == -1) { |
2489 if (res == -1) { |
2341 GST_WARNING_OBJECT (sink, "fnctl failed for %d, removing: %s (%d)", |
2490 GST_WARNING_OBJECT (sink, "fnctl failed for %d, removing: %s (%d)", |
2342 fd, g_strerror (errno), errno); |
2491 fd, g_strerror (errno), errno); |
2343 if (errno == EBADF) { |
2492 if (errno == EBADF) { |
2344 client->status = GST_CLIENT_STATUS_ERROR; |
2493 client->status = GST_CLIENT_STATUS_ERROR; |
2494 /* releases the CLIENTS lock */ |
|
2345 gst_multi_fd_sink_remove_client_link (sink, clients); |
2495 gst_multi_fd_sink_remove_client_link (sink, clients); |
2346 } |
2496 } |
2347 } |
2497 } |
2348 } |
2498 } |
2349 CLIENTS_UNLOCK (sink); |
2499 CLIENTS_UNLOCK (sink); |
2585 multifdsink->def_burst_unit = g_value_get_enum (value); |
2735 multifdsink->def_burst_unit = g_value_get_enum (value); |
2586 break; |
2736 break; |
2587 case PROP_BURST_VALUE: |
2737 case PROP_BURST_VALUE: |
2588 multifdsink->def_burst_value = g_value_get_uint64 (value); |
2738 multifdsink->def_burst_value = g_value_get_uint64 (value); |
2589 break; |
2739 break; |
2740 case PROP_QOS_DSCP: |
|
2741 multifdsink->qos_dscp = g_value_get_int (value); |
|
2742 setup_dscp (multifdsink); |
|
2743 break; |
|
2744 case PROP_HANDLE_READ: |
|
2745 multifdsink->handle_read = g_value_get_boolean (value); |
|
2746 break; |
|
2747 case PROP_RESEND_STREAMHEADER: |
|
2748 multifdsink->resend_streamheader = g_value_get_boolean (value); |
|
2749 break; |
|
2590 |
2750 |
2591 default: |
2751 default: |
2592 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
2752 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
2593 break; |
2753 break; |
2594 } |
2754 } |
2660 case PROP_BURST_UNIT: |
2820 case PROP_BURST_UNIT: |
2661 g_value_set_enum (value, multifdsink->def_burst_unit); |
2821 g_value_set_enum (value, multifdsink->def_burst_unit); |
2662 break; |
2822 break; |
2663 case PROP_BURST_VALUE: |
2823 case PROP_BURST_VALUE: |
2664 g_value_set_uint64 (value, multifdsink->def_burst_value); |
2824 g_value_set_uint64 (value, multifdsink->def_burst_value); |
2825 break; |
|
2826 case PROP_QOS_DSCP: |
|
2827 g_value_set_int (value, multifdsink->qos_dscp); |
|
2828 break; |
|
2829 case PROP_HANDLE_READ: |
|
2830 g_value_set_boolean (value, multifdsink->handle_read); |
|
2831 break; |
|
2832 case PROP_RESEND_STREAMHEADER: |
|
2833 g_value_set_boolean (value, multifdsink->resend_streamheader); |
|
2834 break; |
|
2835 case PROP_NUM_FDS: |
|
2836 g_value_set_uint (value, g_hash_table_size (multifdsink->fd_hash)); |
|
2665 break; |
2837 break; |
2666 |
2838 |
2667 default: |
2839 default: |
2668 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
2840 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
2669 break; |
2841 break; |