1 /* GStreamer
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
4 *
5 * gstfakesrc.c:
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
24 #include <stdlib.h>
25 #include <string.h>
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
31 #include "gstfakesrc.h"
32 #include <gst/gstmarshal.h>
34 #define DEFAULT_SIZEMIN 0
35 #define DEFAULT_SIZEMAX 4096
36 #define DEFAULT_PARENTSIZE 4096*10
37 #define DEFAULT_DATARATE 0
38 #define DEFAULT_SYNC FALSE
40 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
41 GST_PAD_SRC,
42 GST_PAD_ALWAYS,
43 GST_STATIC_CAPS_ANY);
45 GST_DEBUG_CATEGORY_STATIC (gst_fakesrc_debug);
46 #define GST_CAT_DEFAULT gst_fakesrc_debug
48 GstElementDetails gst_fakesrc_details = GST_ELEMENT_DETAILS ("Fake Source",
49 "Source",
50 "Push empty (no data) buffers around",
51 "Erik Walthinsen <omega@cse.ogi.edu>, "
52 "Wim Taymans <wim.taymans@chello.be>");
55 /* FakeSrc signals and args */
56 enum
57 {
58 /* FILL ME */
59 SIGNAL_HANDOFF,
60 LAST_SIGNAL
61 };
63 enum
64 {
65 ARG_0,
66 ARG_NUM_SOURCES,
67 ARG_HAS_LOOP,
68 ARG_HAS_GETRANGE,
69 ARG_OUTPUT,
70 ARG_DATA,
71 ARG_SIZETYPE,
72 ARG_SIZEMIN,
73 ARG_SIZEMAX,
74 ARG_FILLTYPE,
75 ARG_DATARATE,
76 ARG_SYNC,
77 ARG_PATTERN,
78 ARG_NUM_BUFFERS,
79 ARG_EOS,
80 ARG_SIGNAL_HANDOFFS,
81 ARG_SILENT,
82 ARG_DUMP,
83 ARG_PARENTSIZE,
84 ARG_LAST_MESSAGE
85 };
87 GstStaticPadTemplate fakesrc_src_template = GST_STATIC_PAD_TEMPLATE ("src%d",
88 GST_PAD_SRC,
89 GST_PAD_REQUEST,
90 GST_STATIC_CAPS_ANY);
92 #define GST_TYPE_FAKESRC_OUTPUT (gst_fakesrc_output_get_type())
93 static GType
94 gst_fakesrc_output_get_type (void)
95 {
96 static GType fakesrc_output_type = 0;
97 static GEnumValue fakesrc_output[] = {
98 {FAKESRC_FIRST_LAST_LOOP, "1", "First-Last loop"},
99 {FAKESRC_LAST_FIRST_LOOP, "2", "Last-First loop"},
100 {FAKESRC_PING_PONG, "3", "Ping-Pong"},
101 {FAKESRC_ORDERED_RANDOM, "4", "Ordered Random"},
102 {FAKESRC_RANDOM, "5", "Random"},
103 {FAKESRC_PATTERN_LOOP, "6", "Patttern loop"},
104 {FAKESRC_PING_PONG_PATTERN, "7", "Ping-Pong Pattern"},
105 {FAKESRC_GET_ALWAYS_SUCEEDS, "8", "'_get' Always succeeds"},
106 {0, NULL, NULL},
107 };
109 if (!fakesrc_output_type) {
110 fakesrc_output_type =
111 g_enum_register_static ("GstFakeSrcOutput", fakesrc_output);
112 }
113 return fakesrc_output_type;
114 }
116 #define GST_TYPE_FAKESRC_DATA (gst_fakesrc_data_get_type())
117 static GType
118 gst_fakesrc_data_get_type (void)
119 {
120 static GType fakesrc_data_type = 0;
121 static GEnumValue fakesrc_data[] = {
122 {FAKESRC_DATA_ALLOCATE, "1", "Allocate data"},
123 {FAKESRC_DATA_SUBBUFFER, "2", "Subbuffer data"},
124 {0, NULL, NULL},
125 };
127 if (!fakesrc_data_type) {
128 fakesrc_data_type = g_enum_register_static ("GstFakeSrcData", fakesrc_data);
129 }
130 return fakesrc_data_type;
131 }
133 #define GST_TYPE_FAKESRC_SIZETYPE (gst_fakesrc_sizetype_get_type())
134 static GType
135 gst_fakesrc_sizetype_get_type (void)
136 {
137 static GType fakesrc_sizetype_type = 0;
138 static GEnumValue fakesrc_sizetype[] = {
139 {FAKESRC_SIZETYPE_NULL, "1", "Send empty buffers"},
140 {FAKESRC_SIZETYPE_FIXED, "2", "Fixed size buffers (sizemax sized)"},
141 {FAKESRC_SIZETYPE_RANDOM, "3",
142 "Random sized buffers (sizemin <= size <= sizemax)"},
143 {0, NULL, NULL},
144 };
146 if (!fakesrc_sizetype_type) {
147 fakesrc_sizetype_type =
148 g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
149 }
150 return fakesrc_sizetype_type;
151 }
153 #define GST_TYPE_FAKESRC_FILLTYPE (gst_fakesrc_filltype_get_type())
154 static GType
155 gst_fakesrc_filltype_get_type (void)
156 {
157 static GType fakesrc_filltype_type = 0;
158 static GEnumValue fakesrc_filltype[] = {
159 {FAKESRC_FILLTYPE_NOTHING, "1", "Leave data as malloced"},
160 {FAKESRC_FILLTYPE_NULL, "2", "Fill buffers with zeros"},
161 {FAKESRC_FILLTYPE_RANDOM, "3", "Fill buffers with random crap"},
162 {FAKESRC_FILLTYPE_PATTERN, "4", "Fill buffers with pattern 0x00 -> 0xff"},
163 {FAKESRC_FILLTYPE_PATTERN_CONT, "5",
164 "Fill buffers with pattern 0x00 -> 0xff that spans buffers"},
165 {0, NULL, NULL},
166 };
168 if (!fakesrc_filltype_type) {
169 fakesrc_filltype_type =
170 g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
171 }
172 return fakesrc_filltype_type;
173 }
175 #define _do_init(bla) \
176 GST_DEBUG_CATEGORY_INIT (gst_fakesrc_debug, "fakesrc", 0, "fakesrc element");
178 GST_BOILERPLATE_FULL (GstFakeSrc, gst_fakesrc, GstElement, GST_TYPE_ELEMENT,
179 _do_init);
181 static GstPad *gst_fakesrc_request_new_pad (GstElement * element,
182 GstPadTemplate * templ, const gchar * unused);
183 static gboolean gst_fakesrc_activate (GstPad * pad, GstActivateMode mode);
184 static void gst_fakesrc_set_property (GObject * object, guint prop_id,
185 const GValue * value, GParamSpec * pspec);
186 static void gst_fakesrc_get_property (GObject * object, guint prop_id,
187 GValue * value, GParamSpec * pspec);
188 static void gst_fakesrc_set_clock (GstElement * element, GstClock * clock);
190 static GstElementStateReturn gst_fakesrc_change_state (GstElement * element);
192 static void gst_fakesrc_loop (GstPad * pad);
193 static GstFlowReturn gst_fakesrc_get_range (GstPad * pad, guint64 offset,
194 guint length, GstBuffer ** buf);
196 static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 };
198 static void
199 gst_fakesrc_base_init (gpointer g_class)
200 {
201 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
203 gst_element_class_add_pad_template (gstelement_class,
204 gst_static_pad_template_get (&srctemplate));
205 gst_element_class_set_details (gstelement_class, &gst_fakesrc_details);
206 gst_element_class_add_pad_template (gstelement_class,
207 gst_static_pad_template_get (&fakesrc_src_template));
208 }
210 static void
211 gst_fakesrc_class_init (GstFakeSrcClass * klass)
212 {
213 GObjectClass *gobject_class;
214 GstElementClass *gstelement_class;
216 gobject_class = (GObjectClass *) klass;
217 gstelement_class = (GstElementClass *) klass;
219 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
220 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
222 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES,
223 g_param_spec_int ("num-sources", "num-sources", "Number of sources",
224 1, G_MAXINT, 1, G_PARAM_READABLE));
225 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_LOOP,
226 g_param_spec_boolean ("has-loop", "has-loop",
227 "Enable loop-based operation", TRUE,
228 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
229 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_GETRANGE,
230 g_param_spec_boolean ("has-getrange", "has-getrange",
231 "Enable getrange-based operation", TRUE,
232 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
233 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_OUTPUT,
234 g_param_spec_enum ("output", "output", "Output method (currently unused)",
235 GST_TYPE_FAKESRC_OUTPUT, FAKESRC_FIRST_LAST_LOOP, G_PARAM_READWRITE));
236 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA,
237 g_param_spec_enum ("data", "data", "Data allocation method",
238 GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE));
239 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE,
240 g_param_spec_enum ("sizetype", "sizetype",
241 "How to determine buffer sizes", GST_TYPE_FAKESRC_SIZETYPE,
242 FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE));
243 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN,
244 g_param_spec_int ("sizemin", "sizemin", "Minimum buffer size", 0,
245 G_MAXINT, DEFAULT_SIZEMIN, G_PARAM_READWRITE));
246 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX,
247 g_param_spec_int ("sizemax", "sizemax", "Maximum buffer size", 0,
248 G_MAXINT, DEFAULT_SIZEMAX, G_PARAM_READWRITE));
249 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARENTSIZE,
250 g_param_spec_int ("parentsize", "parentsize",
251 "Size of parent buffer for sub-buffered allocation", 0, G_MAXINT,
252 DEFAULT_PARENTSIZE, G_PARAM_READWRITE));
253 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE,
254 g_param_spec_enum ("filltype", "filltype",
255 "How to fill the buffer, if at all", GST_TYPE_FAKESRC_FILLTYPE,
256 FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE));
257 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATARATE,
258 g_param_spec_int ("datarate", "Datarate",
259 "Timestamps buffers with number of bytes per second (0 = none)", 0,
260 G_MAXINT, DEFAULT_DATARATE, G_PARAM_READWRITE));
261 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SYNC,
262 g_param_spec_boolean ("sync", "Sync", "Sync to the clock to the datarate",
263 DEFAULT_SYNC, G_PARAM_READWRITE));
264 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PATTERN,
265 g_param_spec_string ("pattern", "pattern", "pattern", NULL,
266 G_PARAM_READWRITE));
267 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_BUFFERS,
268 g_param_spec_int ("num-buffers", "num-buffers",
269 "Number of buffers to output before sending EOS", -1, G_MAXINT, 0,
270 G_PARAM_READWRITE));
271 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EOS,
272 g_param_spec_boolean ("eos", "eos", "Send out the EOS event?", TRUE,
273 G_PARAM_READWRITE));
274 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
275 g_param_spec_string ("last-message", "last-message",
276 "The last status message", NULL, G_PARAM_READABLE));
277 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
278 g_param_spec_boolean ("silent", "Silent",
279 "Don't produce last_message events", FALSE, G_PARAM_READWRITE));
280 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_HANDOFFS,
281 g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
282 "Send a signal before pushing the buffer", FALSE, G_PARAM_READWRITE));
283 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
284 g_param_spec_boolean ("dump", "Dump", "Dump produced bytes to stdout",
285 FALSE, G_PARAM_READWRITE));
287 gst_fakesrc_signals[SIGNAL_HANDOFF] =
288 g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
289 G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL,
290 gst_marshal_VOID__BOXED_OBJECT, G_TYPE_NONE, 2,
291 GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD);
293 gstelement_class->request_new_pad =
294 GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
295 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
296 gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_fakesrc_set_clock);
297 }
299 static void
300 gst_fakesrc_init (GstFakeSrc * fakesrc)
301 {
302 GstPad *pad;
304 /* create our first output pad */
305 pad =
306 gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
307 "src");
308 gst_element_add_pad (GST_ELEMENT (fakesrc), pad);
310 fakesrc->output = FAKESRC_FIRST_LAST_LOOP;
311 fakesrc->segment_start = -1;
312 fakesrc->segment_end = -1;
313 fakesrc->num_buffers = -1;
314 fakesrc->rt_num_buffers = -1;
315 fakesrc->buffer_count = 0;
316 fakesrc->silent = FALSE;
317 fakesrc->signal_handoffs = FALSE;
318 fakesrc->dump = FALSE;
319 fakesrc->pattern_byte = 0x00;
320 fakesrc->need_flush = FALSE;
321 fakesrc->data = FAKESRC_DATA_ALLOCATE;
322 fakesrc->sizetype = FAKESRC_SIZETYPE_NULL;
323 fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING;
324 fakesrc->sizemin = DEFAULT_SIZEMIN;
325 fakesrc->sizemax = DEFAULT_SIZEMAX;
326 fakesrc->parent = NULL;
327 fakesrc->parentsize = DEFAULT_PARENTSIZE;
328 fakesrc->last_message = NULL;
329 fakesrc->datarate = DEFAULT_DATARATE;
330 fakesrc->sync = DEFAULT_SYNC;
331 fakesrc->pad_mode = GST_ACTIVATE_NONE;
332 }
334 static void
335 gst_fakesrc_set_clock (GstElement * element, GstClock * clock)
336 {
337 GstFakeSrc *src;
339 src = GST_FAKESRC (element);
341 src->clock = clock;
342 }
344 static const GstFormat *
345 gst_fakesrc_get_formats (GstPad * pad)
346 {
347 static const GstFormat formats[] = {
348 GST_FORMAT_DEFAULT,
349 0,
350 };
352 return formats;
353 }
355 static const GstQueryType *
356 gst_fakesrc_get_query_types (GstPad * pad)
357 {
358 static const GstQueryType types[] = {
359 GST_QUERY_TOTAL,
360 GST_QUERY_POSITION,
361 GST_QUERY_START,
362 GST_QUERY_SEGMENT_END,
363 0,
364 };
366 return types;
367 }
369 static gboolean
370 gst_fakesrc_query (GstPad * pad, GstQueryType type,
371 GstFormat * format, gint64 * value)
372 {
373 GstFakeSrc *src = GST_FAKESRC (GST_PAD_PARENT (pad));
375 switch (type) {
376 case GST_QUERY_TOTAL:
377 *value = src->num_buffers;
378 break;
379 case GST_QUERY_POSITION:
380 *value = src->buffer_count;
381 break;
382 case GST_QUERY_START:
383 *value = src->segment_start;
384 break;
385 case GST_QUERY_SEGMENT_END:
386 *value = src->segment_end;
387 break;
388 default:
389 return FALSE;
390 }
391 return TRUE;
392 }
394 static const GstEventMask *
395 gst_fakesrc_get_event_mask (GstPad * pad)
396 {
397 static const GstEventMask masks[] = {
398 {GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP},
399 {GST_EVENT_FLUSH, 0},
400 {0, 0},
401 };
403 return masks;
404 }
406 static gboolean
407 gst_fakesrc_event_handler (GstPad * pad, GstEvent * event)
408 {
409 GstFakeSrc *src;
411 src = GST_FAKESRC (GST_PAD_PARENT (pad));
413 switch (GST_EVENT_TYPE (event)) {
414 case GST_EVENT_SEEK:
415 src->segment_start = GST_EVENT_SEEK_OFFSET (event);
416 src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event);
417 src->buffer_count = src->segment_start;
418 src->segment_loop =
419 GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP;
420 src->need_flush = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH;
421 break;
422 case GST_EVENT_FLUSH:
423 src->need_flush = TRUE;
424 break;
425 default:
426 break;
427 }
428 gst_event_unref (event);
430 return TRUE;
431 }
433 static void
434 gst_fakesrc_set_pad_functions (GstFakeSrc * src, GstPad * pad)
435 {
436 gst_pad_set_activate_function (pad, gst_fakesrc_activate);
437 gst_pad_set_event_function (pad, gst_fakesrc_event_handler);
438 gst_pad_set_event_mask_function (pad, gst_fakesrc_get_event_mask);
439 gst_pad_set_query_function (pad, gst_fakesrc_query);
440 gst_pad_set_query_type_function (pad, gst_fakesrc_get_query_types);
441 gst_pad_set_formats_function (pad, gst_fakesrc_get_formats);
443 if (src->has_loop)
444 gst_pad_set_loop_function (pad, gst_fakesrc_loop);
445 else
446 gst_pad_set_loop_function (pad, NULL);
448 if (src->has_getrange)
449 gst_pad_set_getrange_function (pad, gst_fakesrc_get_range);
450 else
451 gst_pad_set_getrange_function (pad, NULL);
452 }
454 static void
455 gst_fakesrc_set_all_pad_functions (GstFakeSrc * src)
456 {
457 GList *l;
459 for (l = GST_ELEMENT_PADS (src); l; l = l->next)
460 gst_fakesrc_set_pad_functions (src, (GstPad *) l->data);
461 }
463 static GstPad *
464 gst_fakesrc_request_new_pad (GstElement * element, GstPadTemplate * templ,
465 const gchar * unused)
466 {
467 gchar *name;
468 GstPad *srcpad;
469 GstFakeSrc *fakesrc;
471 g_return_val_if_fail (GST_IS_FAKESRC (element), NULL);
473 if (templ->direction != GST_PAD_SRC) {
474 g_warning ("gstfakesrc: request new pad that is not a SRC pad\n");
475 return NULL;
476 }
478 fakesrc = GST_FAKESRC (element);
480 name = g_strdup_printf ("src%d", GST_ELEMENT (fakesrc)->numsrcpads);
482 srcpad = gst_pad_new_from_template (templ, name);
483 gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
484 gst_fakesrc_set_pad_functions (fakesrc, srcpad);
486 g_free (name);
488 return srcpad;
489 }
491 static void
492 gst_fakesrc_alloc_parent (GstFakeSrc * src)
493 {
494 GstBuffer *buf;
496 buf = gst_buffer_new ();
497 GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
498 GST_BUFFER_SIZE (buf) = src->parentsize;
500 src->parent = buf;
501 src->parentoffset = 0;
502 }
504 static void
505 gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value,
506 GParamSpec * pspec)
507 {
508 GstFakeSrc *src;
510 src = GST_FAKESRC (object);
512 switch (prop_id) {
513 case ARG_HAS_LOOP:
514 src->has_loop = g_value_get_boolean (value);
515 gst_fakesrc_set_all_pad_functions (src);
516 break;
517 case ARG_HAS_GETRANGE:
518 src->has_getrange = g_value_get_boolean (value);
519 gst_fakesrc_set_all_pad_functions (src);
520 break;
521 case ARG_OUTPUT:
522 g_warning ("not yet implemented");
523 break;
524 case ARG_DATA:
525 src->data = g_value_get_enum (value);
527 if (src->data == FAKESRC_DATA_SUBBUFFER) {
528 if (!src->parent)
529 gst_fakesrc_alloc_parent (src);
530 } else {
531 if (src->parent) {
532 gst_buffer_unref (src->parent);
533 src->parent = NULL;
534 }
535 }
536 break;
537 case ARG_SIZETYPE:
538 src->sizetype = g_value_get_enum (value);
539 break;
540 case ARG_SIZEMIN:
541 src->sizemin = g_value_get_int (value);
542 break;
543 case ARG_SIZEMAX:
544 src->sizemax = g_value_get_int (value);
545 break;
546 case ARG_PARENTSIZE:
547 src->parentsize = g_value_get_int (value);
548 break;
549 case ARG_FILLTYPE:
550 src->filltype = g_value_get_enum (value);
551 break;
552 case ARG_DATARATE:
553 src->datarate = g_value_get_int (value);
554 break;
555 case ARG_SYNC:
556 src->sync = g_value_get_boolean (value);
557 break;
558 case ARG_PATTERN:
559 break;
560 case ARG_NUM_BUFFERS:
561 src->num_buffers = g_value_get_int (value);
562 break;
563 case ARG_EOS:
564 src->eos = g_value_get_boolean (value);
565 GST_INFO ("will EOS on next buffer");
566 break;
567 case ARG_SILENT:
568 src->silent = g_value_get_boolean (value);
569 break;
570 case ARG_SIGNAL_HANDOFFS:
571 src->signal_handoffs = g_value_get_boolean (value);
572 break;
573 case ARG_DUMP:
574 src->dump = g_value_get_boolean (value);
575 break;
576 default:
577 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
578 break;
579 }
580 }
582 static void
583 gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value,
584 GParamSpec * pspec)
585 {
586 GstFakeSrc *src;
588 /* it's not null if we got it, but it might not be ours */
589 g_return_if_fail (GST_IS_FAKESRC (object));
591 src = GST_FAKESRC (object);
593 switch (prop_id) {
594 case ARG_NUM_SOURCES:
595 g_value_set_int (value, GST_ELEMENT (src)->numsrcpads);
596 break;
597 case ARG_HAS_LOOP:
598 g_value_set_boolean (value, src->has_loop);
599 break;
600 case ARG_HAS_GETRANGE:
601 g_value_set_boolean (value, src->has_getrange);
602 break;
603 case ARG_OUTPUT:
604 g_value_set_enum (value, src->output);
605 break;
606 case ARG_DATA:
607 g_value_set_enum (value, src->data);
608 break;
609 case ARG_SIZETYPE:
610 g_value_set_enum (value, src->sizetype);
611 break;
612 case ARG_SIZEMIN:
613 g_value_set_int (value, src->sizemin);
614 break;
615 case ARG_SIZEMAX:
616 g_value_set_int (value, src->sizemax);
617 break;
618 case ARG_PARENTSIZE:
619 g_value_set_int (value, src->parentsize);
620 break;
621 case ARG_FILLTYPE:
622 g_value_set_enum (value, src->filltype);
623 break;
624 case ARG_DATARATE:
625 g_value_set_int (value, src->datarate);
626 break;
627 case ARG_SYNC:
628 g_value_set_boolean (value, src->sync);
629 break;
630 case ARG_PATTERN:
631 g_value_set_string (value, src->pattern);
632 break;
633 case ARG_NUM_BUFFERS:
634 g_value_set_int (value, src->num_buffers);
635 break;
636 case ARG_EOS:
637 g_value_set_boolean (value, src->eos);
638 break;
639 case ARG_SILENT:
640 g_value_set_boolean (value, src->silent);
641 break;
642 case ARG_SIGNAL_HANDOFFS:
643 g_value_set_boolean (value, src->signal_handoffs);
644 break;
645 case ARG_DUMP:
646 g_value_set_boolean (value, src->dump);
647 break;
648 case ARG_LAST_MESSAGE:
649 g_value_set_string (value, src->last_message);
650 break;
651 default:
652 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
653 break;
654 }
655 }
657 static void
658 gst_fakesrc_prepare_buffer (GstFakeSrc * src, GstBuffer * buf)
659 {
660 if (GST_BUFFER_SIZE (buf) == 0)
661 return;
663 switch (src->filltype) {
664 case FAKESRC_FILLTYPE_NULL:
665 memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
666 break;
667 case FAKESRC_FILLTYPE_RANDOM:
668 {
669 gint i;
670 guint8 *ptr = GST_BUFFER_DATA (buf);
672 for (i = GST_BUFFER_SIZE (buf); i; i--) {
673 *ptr++ = (gint8) ((255.0) * rand () / (RAND_MAX));
674 }
675 break;
676 }
677 case FAKESRC_FILLTYPE_PATTERN:
678 src->pattern_byte = 0x00;
679 case FAKESRC_FILLTYPE_PATTERN_CONT:
680 {
681 gint i;
682 guint8 *ptr = GST_BUFFER_DATA (buf);
684 for (i = GST_BUFFER_SIZE (buf); i; i--) {
685 *ptr++ = src->pattern_byte++;
686 }
687 break;
688 }
689 case FAKESRC_FILLTYPE_NOTHING:
690 default:
691 break;
692 }
693 }
695 static GstBuffer *
696 gst_fakesrc_alloc_buffer (GstFakeSrc * src, guint size)
697 {
698 GstBuffer *buf;
700 buf = gst_buffer_new ();
701 GST_BUFFER_SIZE (buf) = size;
703 if (size != 0) {
704 switch (src->filltype) {
705 case FAKESRC_FILLTYPE_NOTHING:
706 GST_BUFFER_DATA (buf) = g_malloc (size);
707 break;
708 case FAKESRC_FILLTYPE_NULL:
709 GST_BUFFER_DATA (buf) = g_malloc0 (size);
710 break;
711 case FAKESRC_FILLTYPE_RANDOM:
712 case FAKESRC_FILLTYPE_PATTERN:
713 case FAKESRC_FILLTYPE_PATTERN_CONT:
714 default:
715 GST_BUFFER_DATA (buf) = g_malloc (size);
716 gst_fakesrc_prepare_buffer (src, buf);
717 break;
718 }
719 }
721 return buf;
722 }
724 static guint
725 gst_fakesrc_get_size (GstFakeSrc * src)
726 {
727 guint size;
729 switch (src->sizetype) {
730 case FAKESRC_SIZETYPE_FIXED:
731 size = src->sizemax;
732 break;
733 case FAKESRC_SIZETYPE_RANDOM:
734 size =
735 src->sizemin +
736 (guint8) (((gfloat) src->sizemax) * rand () / (RAND_MAX +
737 (gfloat) src->sizemin));
738 break;
739 case FAKESRC_SIZETYPE_NULL:
740 default:
741 size = 0;
742 break;
743 }
745 return size;
746 }
748 static GstBuffer *
749 gst_fakesrc_create_buffer (GstFakeSrc * src)
750 {
751 GstBuffer *buf;
752 guint size;
753 gboolean dump = src->dump;
755 size = gst_fakesrc_get_size (src);
756 if (size == 0)
757 return gst_buffer_new ();
759 switch (src->data) {
760 case FAKESRC_DATA_ALLOCATE:
761 buf = gst_fakesrc_alloc_buffer (src, size);
762 break;
763 case FAKESRC_DATA_SUBBUFFER:
764 /* see if we have a parent to subbuffer */
765 if (!src->parent) {
766 gst_fakesrc_alloc_parent (src);
767 g_assert (src->parent);
768 }
769 /* see if it's large enough */
770 if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
771 buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
772 src->parentoffset += size;
773 } else {
774 /* the parent is useless now */
775 gst_buffer_unref (src->parent);
776 src->parent = NULL;
777 /* try again (this will allocate a new parent) */
778 return gst_fakesrc_create_buffer (src);
779 }
780 gst_fakesrc_prepare_buffer (src, buf);
781 break;
782 default:
783 g_warning ("fakesrc: dunno how to allocate buffers !");
784 buf = gst_buffer_new ();
785 break;
786 }
787 if (dump) {
788 gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
789 }
791 return buf;
792 }
794 static GstFlowReturn
795 gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length,
796 GstBuffer ** ret)
797 {
798 GstFakeSrc *src;
799 GstBuffer *buf;
800 GstClockTime time;
802 src = GST_FAKESRC (GST_OBJECT_PARENT (pad));
804 if (src->buffer_count == src->segment_end) {
805 if (src->segment_loop) {
806 //gst_pad_push_event (pad, gst_event_new (GST_EVENT_SEGMENT_DONE));
807 } else {
808 gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
809 return GST_FLOW_UNEXPECTED;
810 }
811 }
813 if (src->rt_num_buffers == 0) {
814 gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
815 return GST_FLOW_UNEXPECTED;
816 } else {
817 if (src->rt_num_buffers > 0)
818 src->rt_num_buffers--;
819 }
821 if (src->eos) {
822 GST_INFO ("fakesrc is setting eos on pad");
823 gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
824 return GST_FLOW_UNEXPECTED;
825 }
827 buf = gst_fakesrc_create_buffer (src);
828 GST_BUFFER_OFFSET (buf) = src->buffer_count++;
830 time = GST_CLOCK_TIME_NONE;
832 if (src->datarate > 0) {
833 time = (src->bytes_sent * GST_SECOND) / src->datarate;
834 if (src->sync) {
835 /* gst_element_wait (GST_ELEMENT (src), time); */
836 }
838 GST_BUFFER_DURATION (buf) =
839 GST_BUFFER_SIZE (buf) * GST_SECOND / src->datarate;
840 }
841 GST_BUFFER_TIMESTAMP (buf) = time;
843 if (!src->silent) {
844 g_free (src->last_message);
846 src->last_message =
847 g_strdup_printf ("get ******* (%s:%s)> (%d bytes, %"
848 G_GUINT64_FORMAT " ) %p", GST_DEBUG_PAD_NAME (pad),
849 GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
851 g_object_notify (G_OBJECT (src), "last_message");
852 }
854 if (src->signal_handoffs) {
855 GST_LOG_OBJECT (src, "pre handoff emit");
856 g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
857 buf, pad);
858 GST_LOG_OBJECT (src, "post handoff emit");
859 }
861 src->bytes_sent += GST_BUFFER_SIZE (buf);
863 *ret = buf;
864 return GST_FLOW_OK;
865 }
867 static GstFlowReturn
868 gst_fakesrc_get_range (GstPad * pad, guint64 offset, guint length,
869 GstBuffer ** ret)
870 {
871 GstFlowReturn fret;
873 g_assert (GST_FAKESRC (GST_OBJECT_PARENT (pad))->pad_mode ==
874 GST_ACTIVATE_PULL);
876 GST_STREAM_LOCK (pad);
878 fret = gst_fakesrc_get_range_unlocked (pad, offset, length, ret);
880 GST_STREAM_UNLOCK (pad);
882 return fret;
883 }
885 static void
886 gst_fakesrc_loop (GstPad * pad)
887 {
888 GstFakeSrc *src;
889 GstBuffer *buf = NULL;
890 GstFlowReturn ret;
892 src = GST_FAKESRC (GST_OBJECT_PARENT (pad));
894 g_assert (src->pad_mode == GST_ACTIVATE_PUSH);
896 GST_STREAM_LOCK (pad);
897 if (src->need_flush) {
898 src->need_flush = FALSE;
899 gst_pad_push_event (pad, gst_event_new (GST_EVENT_FLUSH));
900 }
902 ret = gst_fakesrc_get_range_unlocked (pad, src->buffer_count,
903 DEFAULT_SIZEMAX, &buf);
904 if (ret != GST_FLOW_OK) {
905 goto pause;
906 }
908 ret = gst_pad_push (pad, buf);
909 if (ret != GST_FLOW_OK) {
910 goto pause;
911 }
913 GST_STREAM_UNLOCK (pad);
914 return;
916 pause:
917 gst_task_pause (GST_RPAD_TASK (pad));
918 GST_STREAM_UNLOCK (pad);
919 return;
920 }
922 static gboolean
923 gst_fakesrc_activate (GstPad * pad, GstActivateMode mode)
924 {
925 gboolean result = FALSE;
926 GstFakeSrc *fakesrc;
928 fakesrc = GST_FAKESRC (GST_OBJECT_PARENT (pad));
930 switch (mode) {
931 case GST_ACTIVATE_PUSH:
932 /* if we have a scheduler we can start the task */
933 g_return_val_if_fail (fakesrc->has_loop, FALSE);
934 if (GST_ELEMENT_SCHEDULER (fakesrc)) {
935 GST_STREAM_LOCK (pad);
936 GST_RPAD_TASK (pad) =
937 gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (fakesrc),
938 (GstTaskFunction) gst_fakesrc_loop, pad);
940 gst_task_start (GST_RPAD_TASK (pad));
941 GST_STREAM_UNLOCK (pad);
942 result = TRUE;
943 }
944 break;
945 case GST_ACTIVATE_PULL:
946 g_return_val_if_fail (fakesrc->has_getrange, FALSE);
947 result = TRUE;
948 break;
949 case GST_ACTIVATE_NONE:
950 /* step 1, unblock clock sync (if any) */
952 /* step 2, make sure streaming finishes */
953 GST_STREAM_LOCK (pad);
954 /* step 3, stop the task */
955 if (GST_RPAD_TASK (pad)) {
956 gst_task_stop (GST_RPAD_TASK (pad));
957 gst_object_unref (GST_OBJECT (GST_RPAD_TASK (pad)));
958 GST_RPAD_TASK (pad) = NULL;
959 }
960 GST_STREAM_UNLOCK (pad);
962 result = TRUE;
963 break;
964 }
966 fakesrc->pad_mode = mode;
968 return result;
969 }
971 static GstElementStateReturn
972 gst_fakesrc_change_state (GstElement * element)
973 {
974 GstFakeSrc *fakesrc;
975 GstElementStateReturn result = GST_STATE_FAILURE;
977 g_return_val_if_fail (GST_IS_FAKESRC (element), result);
979 fakesrc = GST_FAKESRC (element);
981 switch (GST_STATE_TRANSITION (element)) {
982 case GST_STATE_NULL_TO_READY:
983 break;
984 case GST_STATE_READY_TO_PAUSED:
985 {
986 fakesrc->buffer_count = 0;
987 fakesrc->pattern_byte = 0x00;
988 fakesrc->need_flush = FALSE;
989 fakesrc->eos = FALSE;
990 fakesrc->bytes_sent = 0;
991 fakesrc->rt_num_buffers = fakesrc->num_buffers;
992 break;
993 }
994 case GST_STATE_PAUSED_TO_PLAYING:
995 break;
996 }
998 result = GST_ELEMENT_CLASS (parent_class)->change_state (element);
1000 switch (GST_STATE_TRANSITION (element)) {
1001 case GST_STATE_PLAYING_TO_PAUSED:
1002 break;
1003 case GST_STATE_PAUSED_TO_READY:
1004 if (fakesrc->parent) {
1005 gst_buffer_unref (fakesrc->parent);
1006 fakesrc->parent = NULL;
1007 }
1008 g_free (fakesrc->last_message);
1009 fakesrc->last_message = NULL;
1010 break;
1011 case GST_STATE_READY_TO_NULL:
1012 break;
1013 default:
1014 break;
1015 }
1017 return result;
1018 }