1 /* GStreamer
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wim@fluendo.com>
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 */
22 /**
23 * SECTION:element-fakesrc
24 * @see_also: #GstFakeSink
25 *
26 * The fakesrc element is a multipurpose element that can generate
27 * a wide range of buffers and can operate in various scheduling modes.
28 *
29 * It is mostly used as a testing element, one trivial example for testing
30 * basic <application>GStreamer</application> core functionality is:
31 *
32 * <refsect2>
33 * <title>Example launch line</title>
34 * |[
35 * gst-launch -v fakesrc num-buffers=5 ! fakesink
36 * ]| This pipeline will push 5 empty buffers to the fakesink element and then
37 * sends an EOS.
38 * </refsect2>
39 *
40 * Last reviewed on 2008-06-20 (0.10.21)
41 */
43 /* FIXME: this ignores basesrc::blocksize property, which could be used as an
44 * alias to ::sizemax (see gst_base_src_get_blocksize()).
45 */
47 #ifdef HAVE_CONFIG_H
48 # include "config.h"
49 #endif
51 #include <stdlib.h>
52 #include <string.h>
54 #include "gstfakesrc.h"
55 #include <gst/gstmarshal.h>
57 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
58 GST_PAD_SRC,
59 GST_PAD_ALWAYS,
60 GST_STATIC_CAPS_ANY);
62 GST_DEBUG_CATEGORY_STATIC (gst_fake_src_debug);
63 #define GST_CAT_DEFAULT gst_fake_src_debug
65 /* FakeSrc signals and args */
66 enum
67 {
68 /* FILL ME */
69 SIGNAL_HANDOFF,
70 LAST_SIGNAL
71 };
73 #define DEFAULT_OUTPUT FAKE_SRC_FIRST_LAST_LOOP
74 #define DEFAULT_DATA FAKE_SRC_DATA_ALLOCATE
75 #define DEFAULT_SIZETYPE FAKE_SRC_SIZETYPE_EMPTY
76 #define DEFAULT_SIZEMIN 0
77 #define DEFAULT_SIZEMAX 4096
78 #define DEFAULT_FILLTYPE FAKE_SRC_FILLTYPE_ZERO
79 #define DEFAULT_DATARATE 0
80 #define DEFAULT_SYNC FALSE
81 #define DEFAULT_PATTERN NULL
82 #define DEFAULT_EOS FALSE
83 #define DEFAULT_SIGNAL_HANDOFFS FALSE
84 #define DEFAULT_SILENT FALSE
85 #define DEFAULT_DUMP FALSE
86 #define DEFAULT_PARENTSIZE 4096*10
87 #define DEFAULT_CAN_ACTIVATE_PULL TRUE
88 #define DEFAULT_CAN_ACTIVATE_PUSH TRUE
89 #define DEFAULT_FORMAT GST_FORMAT_BYTES
91 enum
92 {
93 PROP_0,
94 PROP_OUTPUT,
95 PROP_DATA,
96 PROP_SIZETYPE,
97 PROP_SIZEMIN,
98 PROP_SIZEMAX,
99 PROP_FILLTYPE,
100 PROP_DATARATE,
101 PROP_SYNC,
102 PROP_PATTERN,
103 PROP_EOS,
104 PROP_SIGNAL_HANDOFFS,
105 PROP_SILENT,
106 PROP_DUMP,
107 PROP_PARENTSIZE,
108 PROP_LAST_MESSAGE,
109 PROP_CAN_ACTIVATE_PULL,
110 PROP_CAN_ACTIVATE_PUSH,
111 PROP_IS_LIVE,
112 PROP_FORMAT,
113 PROP_LAST,
114 };
116 /* not implemented
117 #define GST_TYPE_FAKE_SRC_OUTPUT (gst_fake_src_output_get_type())
118 static GType
119 gst_fake_src_output_get_type (void)
120 {
121 static GType fakesrc_output_type = 0;
122 static const GEnumValue fakesrc_output[] = {
123 {FAKE_SRC_FIRST_LAST_LOOP, "1", "First-Last loop"},
124 {FAKE_SRC_LAST_FIRST_LOOP, "2", "Last-First loop"},
125 {FAKE_SRC_PING_PONG, "3", "Ping-Pong"},
126 {FAKE_SRC_ORDERED_RANDOM, "4", "Ordered Random"},
127 {FAKE_SRC_RANDOM, "5", "Random"},
128 {FAKE_SRC_PATTERN_LOOP, "6", "Patttern loop"},
129 {FAKE_SRC_PING_PONG_PATTERN, "7", "Ping-Pong Pattern"},
130 {FAKE_SRC_GET_ALWAYS_SUCEEDS, "8", "'_get' Always succeeds"},
131 {0, NULL, NULL},
132 };
134 if (!fakesrc_output_type) {
135 fakesrc_output_type =
136 g_enum_register_static ("GstFakeSrcOutput", fakesrc_output);
137 }
138 return fakesrc_output_type;
139 }
140 */
142 #define GST_TYPE_FAKE_SRC_DATA (gst_fake_src_data_get_type())
143 static GType
144 gst_fake_src_data_get_type (void)
145 {
146 static GType fakesrc_data_type = 0;
147 static const GEnumValue fakesrc_data[] = {
148 {FAKE_SRC_DATA_ALLOCATE, "Allocate data", "allocate"},
149 {FAKE_SRC_DATA_SUBBUFFER, "Subbuffer data", "subbuffer"},
150 {0, NULL, NULL},
151 };
153 if (!fakesrc_data_type) {
154 fakesrc_data_type =
155 g_enum_register_static ("GstFakeSrcDataType", fakesrc_data);
156 }
157 return fakesrc_data_type;
158 }
160 #define GST_TYPE_FAKE_SRC_SIZETYPE (gst_fake_src_sizetype_get_type())
161 static GType
162 gst_fake_src_sizetype_get_type (void)
163 {
164 static GType fakesrc_sizetype_type = 0;
165 static const GEnumValue fakesrc_sizetype[] = {
166 {FAKE_SRC_SIZETYPE_EMPTY, "Send empty buffers", "empty"},
167 {FAKE_SRC_SIZETYPE_FIXED, "Fixed size buffers (sizemax sized)", "fixed"},
168 {FAKE_SRC_SIZETYPE_RANDOM,
169 "Random sized buffers (sizemin <= size <= sizemax)", "random"},
170 {0, NULL, NULL},
171 };
173 if (!fakesrc_sizetype_type) {
174 fakesrc_sizetype_type =
175 g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
176 }
177 return fakesrc_sizetype_type;
178 }
180 #define GST_TYPE_FAKE_SRC_FILLTYPE (gst_fake_src_filltype_get_type())
181 static GType
182 gst_fake_src_filltype_get_type (void)
183 {
184 static GType fakesrc_filltype_type = 0;
185 static const GEnumValue fakesrc_filltype[] = {
186 {FAKE_SRC_FILLTYPE_NOTHING, "Leave data as malloced", "nothing"},
187 {FAKE_SRC_FILLTYPE_ZERO, "Fill buffers with zeros", "zero"},
188 {FAKE_SRC_FILLTYPE_RANDOM, "Fill buffers with random crap", "random"},
189 {FAKE_SRC_FILLTYPE_PATTERN, "Fill buffers with pattern 0x00 -> 0xff",
190 "pattern"},
191 {FAKE_SRC_FILLTYPE_PATTERN_CONT,
192 "Fill buffers with pattern 0x00 -> 0xff that spans buffers",
193 "pattern-span"},
194 {0, NULL, NULL},
195 };
197 if (!fakesrc_filltype_type) {
198 fakesrc_filltype_type =
199 g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
200 }
201 return fakesrc_filltype_type;
202 }
204 #define _do_init(bla) \
205 GST_DEBUG_CATEGORY_INIT (gst_fake_src_debug, "fakesrc", 0, "fakesrc element");
207 GST_BOILERPLATE_FULL (GstFakeSrc, gst_fake_src, GstBaseSrc, GST_TYPE_BASE_SRC,
208 _do_init);
210 static void gst_fake_src_finalize (GObject * object);
211 static void gst_fake_src_set_property (GObject * object, guint prop_id,
212 const GValue * value, GParamSpec * pspec);
213 static void gst_fake_src_get_property (GObject * object, guint prop_id,
214 GValue * value, GParamSpec * pspec);
216 static gboolean gst_fake_src_start (GstBaseSrc * basesrc);
217 static gboolean gst_fake_src_stop (GstBaseSrc * basesrc);
218 static gboolean gst_fake_src_is_seekable (GstBaseSrc * basesrc);
220 static gboolean gst_fake_src_event_handler (GstBaseSrc * src, GstEvent * event);
221 static void gst_fake_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
222 GstClockTime * start, GstClockTime * end);
223 static GstFlowReturn gst_fake_src_create (GstBaseSrc * src, guint64 offset,
224 guint length, GstBuffer ** buf);
226 static guint gst_fake_src_signals[LAST_SIGNAL] = { 0 };
228 static GParamSpec *pspec_last_message = NULL;
230 static void
231 marshal_VOID__MINIOBJECT_OBJECT (GClosure * closure, GValue * return_value,
232 guint n_param_values, const GValue * param_values, gpointer invocation_hint,
233 gpointer marshal_data)
234 {
235 typedef void (*marshalfunc_VOID__MINIOBJECT_OBJECT) (gpointer obj,
236 gpointer arg1, gpointer arg2, gpointer data2);
237 register marshalfunc_VOID__MINIOBJECT_OBJECT callback;
238 register GCClosure *cc = (GCClosure *) closure;
239 register gpointer data1, data2;
241 g_return_if_fail (n_param_values == 3);
243 if (G_CCLOSURE_SWAP_DATA (closure)) {
244 data1 = closure->data;
245 data2 = g_value_peek_pointer (param_values + 0);
246 } else {
247 data1 = g_value_peek_pointer (param_values + 0);
248 data2 = closure->data;
249 }
250 callback =
251 (marshalfunc_VOID__MINIOBJECT_OBJECT) (marshal_data ? marshal_data :
252 cc->callback);
254 callback (data1, gst_value_get_mini_object (param_values + 1),
255 g_value_get_object (param_values + 2), data2);
256 }
258 static void
259 gst_fake_src_base_init (gpointer g_class)
260 {
261 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
263 gst_element_class_set_details_simple (gstelement_class,
264 "Fake Source",
265 "Source",
266 "Push empty (no data) buffers around",
267 "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
268 gst_element_class_add_pad_template (gstelement_class,
269 gst_static_pad_template_get (&srctemplate));
270 }
272 static void
273 gst_fake_src_class_init (GstFakeSrcClass * klass)
274 {
275 GObjectClass *gobject_class;
276 GstBaseSrcClass *gstbase_src_class;
278 gobject_class = G_OBJECT_CLASS (klass);
279 gstbase_src_class = GST_BASE_SRC_CLASS (klass);
281 gobject_class->finalize = gst_fake_src_finalize;
283 gobject_class->set_property = gst_fake_src_set_property;
284 gobject_class->get_property = gst_fake_src_get_property;
286 /*
287 FIXME: this is not implemented; would make sense once basesrc and fakesrc
288 support multiple pads
289 g_object_class_install_property (gobject_class, PROP_OUTPUT,
290 g_param_spec_enum ("output", "output", "Output method (currently unused)",
291 GST_TYPE_FAKE_SRC_OUTPUT, DEFAULT_OUTPUT, G_PARAM_READWRITE));
292 */
293 g_object_class_install_property (gobject_class, PROP_DATA,
294 g_param_spec_enum ("data", "data", "Data allocation method",
295 GST_TYPE_FAKE_SRC_DATA, DEFAULT_DATA,
296 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
297 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIZETYPE,
298 g_param_spec_enum ("sizetype", "sizetype",
299 "How to determine buffer sizes", GST_TYPE_FAKE_SRC_SIZETYPE,
300 DEFAULT_SIZETYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
301 g_object_class_install_property (gobject_class, PROP_SIZEMIN,
302 g_param_spec_int ("sizemin", "sizemin", "Minimum buffer size", 0,
303 G_MAXINT, DEFAULT_SIZEMIN,
304 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
305 g_object_class_install_property (gobject_class, PROP_SIZEMAX,
306 g_param_spec_int ("sizemax", "sizemax", "Maximum buffer size", 0,
307 G_MAXINT, DEFAULT_SIZEMAX,
308 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
309 g_object_class_install_property (gobject_class, PROP_PARENTSIZE,
310 g_param_spec_int ("parentsize", "parentsize",
311 "Size of parent buffer for sub-buffered allocation", 0, G_MAXINT,
312 DEFAULT_PARENTSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
313 g_object_class_install_property (gobject_class, PROP_FILLTYPE,
314 g_param_spec_enum ("filltype", "filltype",
315 "How to fill the buffer, if at all", GST_TYPE_FAKE_SRC_FILLTYPE,
316 DEFAULT_FILLTYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
317 g_object_class_install_property (gobject_class, PROP_DATARATE,
318 g_param_spec_int ("datarate", "Datarate",
319 "Timestamps buffers with number of bytes per second (0 = none)", 0,
320 G_MAXINT, DEFAULT_DATARATE,
321 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
322 g_object_class_install_property (gobject_class, PROP_SYNC,
323 g_param_spec_boolean ("sync", "Sync", "Sync to the clock to the datarate",
324 DEFAULT_SYNC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
325 g_object_class_install_property (gobject_class, PROP_PATTERN,
326 g_param_spec_string ("pattern", "pattern", "pattern", DEFAULT_PATTERN,
327 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
328 pspec_last_message = g_param_spec_string ("last-message", "last-message",
329 "The last status message", NULL,
330 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
331 g_object_class_install_property (gobject_class, PROP_LAST_MESSAGE,
332 pspec_last_message);
333 g_object_class_install_property (gobject_class, PROP_SILENT,
334 g_param_spec_boolean ("silent", "Silent",
335 "Don't produce last_message events", DEFAULT_SILENT,
336 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
337 g_object_class_install_property (gobject_class, PROP_SIGNAL_HANDOFFS,
338 g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
339 "Send a signal before pushing the buffer", DEFAULT_SIGNAL_HANDOFFS,
340 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
341 g_object_class_install_property (gobject_class, PROP_DUMP,
342 g_param_spec_boolean ("dump", "Dump", "Dump buffer contents to stdout",
343 DEFAULT_DUMP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
344 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH,
345 g_param_spec_boolean ("can-activate-push", "Can activate push",
346 "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
347 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
348 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
349 g_param_spec_boolean ("can-activate-pull", "Can activate pull",
350 "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
351 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
352 g_object_class_install_property (gobject_class, PROP_IS_LIVE,
353 g_param_spec_boolean ("is-live", "Is this a live source",
354 "True if the element cannot produce data in PAUSED", FALSE,
355 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
356 /**
357 * GstFakeSrc:format
358 *
359 * Set the format of the newsegment events to produce.
360 *
361 * Since: 0.10.20
362 */
363 g_object_class_install_property (gobject_class, PROP_FORMAT,
364 g_param_spec_enum ("format", "Format",
365 "The format of the segment events", GST_TYPE_FORMAT,
366 DEFAULT_FORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
368 /**
369 * GstFakeSrc::handoff:
370 * @fakesrc: the fakesrc instance
371 * @buffer: the buffer that will be pushed
372 * @pad: the pad that will sent it
373 *
374 * This signal gets emitted before sending the buffer.
375 */
376 gst_fake_src_signals[SIGNAL_HANDOFF] =
377 g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
378 G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL,
379 marshal_VOID__MINIOBJECT_OBJECT, G_TYPE_NONE, 2, GST_TYPE_BUFFER,
380 GST_TYPE_PAD);
382 gstbase_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fake_src_is_seekable);
383 gstbase_src_class->start = GST_DEBUG_FUNCPTR (gst_fake_src_start);
384 gstbase_src_class->stop = GST_DEBUG_FUNCPTR (gst_fake_src_stop);
385 gstbase_src_class->event = GST_DEBUG_FUNCPTR (gst_fake_src_event_handler);
386 gstbase_src_class->get_times = GST_DEBUG_FUNCPTR (gst_fake_src_get_times);
387 gstbase_src_class->create = GST_DEBUG_FUNCPTR (gst_fake_src_create);
388 }
390 static void
391 gst_fake_src_init (GstFakeSrc * fakesrc, GstFakeSrcClass * g_class)
392 {
393 fakesrc->output = FAKE_SRC_FIRST_LAST_LOOP;
394 fakesrc->buffer_count = 0;
395 fakesrc->silent = DEFAULT_SILENT;
396 fakesrc->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
397 fakesrc->dump = DEFAULT_DUMP;
398 fakesrc->pattern_byte = 0x00;
399 fakesrc->data = FAKE_SRC_DATA_ALLOCATE;
400 fakesrc->sizetype = FAKE_SRC_SIZETYPE_EMPTY;
401 fakesrc->filltype = FAKE_SRC_FILLTYPE_NOTHING;
402 fakesrc->sizemin = DEFAULT_SIZEMIN;
403 fakesrc->sizemax = DEFAULT_SIZEMAX;
404 fakesrc->parent = NULL;
405 fakesrc->parentsize = DEFAULT_PARENTSIZE;
406 fakesrc->last_message = NULL;
407 fakesrc->datarate = DEFAULT_DATARATE;
408 fakesrc->sync = DEFAULT_SYNC;
409 fakesrc->format = DEFAULT_FORMAT;
410 }
412 static void
413 gst_fake_src_finalize (GObject * object)
414 {
415 GstFakeSrc *src;
417 src = GST_FAKE_SRC (object);
419 g_free (src->last_message);
420 if (src->parent) {
421 gst_buffer_unref (src->parent);
422 src->parent = NULL;
423 }
425 G_OBJECT_CLASS (parent_class)->finalize (object);
426 }
428 static gboolean
429 gst_fake_src_event_handler (GstBaseSrc * basesrc, GstEvent * event)
430 {
431 GstFakeSrc *src;
433 src = GST_FAKE_SRC (basesrc);
435 if (!src->silent) {
436 const GstStructure *s;
437 gchar *sstr;
439 GST_OBJECT_LOCK (src);
440 g_free (src->last_message);
442 if ((s = gst_event_get_structure (event)))
443 sstr = gst_structure_to_string (s);
444 else
445 sstr = g_strdup ("");
447 src->last_message =
448 g_strdup_printf ("event ******* (%s:%s) E (type: %d, %s) %p",
449 GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad),
450 GST_EVENT_TYPE (event), sstr, event);
451 g_free (sstr);
452 GST_OBJECT_UNLOCK (src);
454 #if !GLIB_CHECK_VERSION(2,26,0)
455 g_object_notify ((GObject *) src, "last-message");
456 #else
457 g_object_notify_by_pspec ((GObject *) src, pspec_last_message);
458 #endif
459 }
461 return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event);
462 }
464 static void
465 gst_fake_src_alloc_parent (GstFakeSrc * src)
466 {
467 GstBuffer *buf;
469 buf = gst_buffer_new ();
470 GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
471 GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
472 GST_BUFFER_SIZE (buf) = src->parentsize;
474 src->parent = buf;
475 src->parentoffset = 0;
476 }
478 static void
479 gst_fake_src_set_property (GObject * object, guint prop_id,
480 const GValue * value, GParamSpec * pspec)
481 {
482 GstFakeSrc *src;
483 GstBaseSrc *basesrc;
485 src = GST_FAKE_SRC (object);
486 basesrc = GST_BASE_SRC (object);
488 switch (prop_id) {
489 case PROP_OUTPUT:
490 g_warning ("not yet implemented");
491 break;
492 case PROP_DATA:
493 src->data = g_value_get_enum (value);
495 if (src->data == FAKE_SRC_DATA_SUBBUFFER) {
496 if (!src->parent)
497 gst_fake_src_alloc_parent (src);
498 } else {
499 if (src->parent) {
500 gst_buffer_unref (src->parent);
501 src->parent = NULL;
502 }
503 }
504 break;
505 case PROP_SIZETYPE:
506 src->sizetype = g_value_get_enum (value);
507 break;
508 case PROP_SIZEMIN:
509 src->sizemin = g_value_get_int (value);
510 break;
511 case PROP_SIZEMAX:
512 src->sizemax = g_value_get_int (value);
513 break;
514 case PROP_PARENTSIZE:
515 src->parentsize = g_value_get_int (value);
516 break;
517 case PROP_FILLTYPE:
518 src->filltype = g_value_get_enum (value);
519 break;
520 case PROP_DATARATE:
521 src->datarate = g_value_get_int (value);
522 break;
523 case PROP_SYNC:
524 src->sync = g_value_get_boolean (value);
525 break;
526 case PROP_PATTERN:
527 break;
528 case PROP_SILENT:
529 src->silent = g_value_get_boolean (value);
530 break;
531 case PROP_SIGNAL_HANDOFFS:
532 src->signal_handoffs = g_value_get_boolean (value);
533 break;
534 case PROP_DUMP:
535 src->dump = g_value_get_boolean (value);
536 break;
537 case PROP_CAN_ACTIVATE_PUSH:
538 g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
539 GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
540 break;
541 case PROP_CAN_ACTIVATE_PULL:
542 g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
543 src->can_activate_pull = g_value_get_boolean (value);
544 break;
545 case PROP_IS_LIVE:
546 gst_base_src_set_live (basesrc, g_value_get_boolean (value));
547 break;
548 case PROP_FORMAT:
549 src->format = g_value_get_enum (value);
550 break;
551 default:
552 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
553 break;
554 }
555 }
557 static void
558 gst_fake_src_get_property (GObject * object, guint prop_id, GValue * value,
559 GParamSpec * pspec)
560 {
561 GstFakeSrc *src;
562 GstBaseSrc *basesrc;
564 g_return_if_fail (GST_IS_FAKE_SRC (object));
566 src = GST_FAKE_SRC (object);
567 basesrc = GST_BASE_SRC (object);
569 switch (prop_id) {
570 case PROP_OUTPUT:
571 g_value_set_enum (value, src->output);
572 break;
573 case PROP_DATA:
574 g_value_set_enum (value, src->data);
575 break;
576 case PROP_SIZETYPE:
577 g_value_set_enum (value, src->sizetype);
578 break;
579 case PROP_SIZEMIN:
580 g_value_set_int (value, src->sizemin);
581 break;
582 case PROP_SIZEMAX:
583 g_value_set_int (value, src->sizemax);
584 break;
585 case PROP_PARENTSIZE:
586 g_value_set_int (value, src->parentsize);
587 break;
588 case PROP_FILLTYPE:
589 g_value_set_enum (value, src->filltype);
590 break;
591 case PROP_DATARATE:
592 g_value_set_int (value, src->datarate);
593 break;
594 case PROP_SYNC:
595 g_value_set_boolean (value, src->sync);
596 break;
597 case PROP_PATTERN:
598 g_value_set_string (value, src->pattern);
599 break;
600 case PROP_SILENT:
601 g_value_set_boolean (value, src->silent);
602 break;
603 case PROP_SIGNAL_HANDOFFS:
604 g_value_set_boolean (value, src->signal_handoffs);
605 break;
606 case PROP_DUMP:
607 g_value_set_boolean (value, src->dump);
608 break;
609 case PROP_LAST_MESSAGE:
610 GST_OBJECT_LOCK (src);
611 g_value_set_string (value, src->last_message);
612 GST_OBJECT_UNLOCK (src);
613 break;
614 case PROP_CAN_ACTIVATE_PUSH:
615 g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
616 break;
617 case PROP_CAN_ACTIVATE_PULL:
618 g_value_set_boolean (value, src->can_activate_pull);
619 break;
620 case PROP_IS_LIVE:
621 g_value_set_boolean (value, gst_base_src_is_live (basesrc));
622 break;
623 case PROP_FORMAT:
624 g_value_set_enum (value, src->format);
625 break;
626 default:
627 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
628 break;
629 }
630 }
632 static void
633 gst_fake_src_prepare_buffer (GstFakeSrc * src, GstBuffer * buf)
634 {
635 if (GST_BUFFER_SIZE (buf) == 0)
636 return;
638 switch (src->filltype) {
639 case FAKE_SRC_FILLTYPE_ZERO:
640 memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
641 break;
642 case FAKE_SRC_FILLTYPE_RANDOM:
643 {
644 gint i;
645 guint8 *ptr = GST_BUFFER_DATA (buf);
647 for (i = GST_BUFFER_SIZE (buf); i; i--) {
648 *ptr++ = g_random_int_range (0, 256);
649 }
650 break;
651 }
652 case FAKE_SRC_FILLTYPE_PATTERN:
653 src->pattern_byte = 0x00;
654 case FAKE_SRC_FILLTYPE_PATTERN_CONT:
655 {
656 gint i;
657 guint8 *ptr = GST_BUFFER_DATA (buf);
659 for (i = GST_BUFFER_SIZE (buf); i; i--) {
660 *ptr++ = src->pattern_byte++;
661 }
662 break;
663 }
664 case FAKE_SRC_FILLTYPE_NOTHING:
665 default:
666 break;
667 }
668 }
670 static GstBuffer *
671 gst_fake_src_alloc_buffer (GstFakeSrc * src, guint size)
672 {
673 GstBuffer *buf;
675 buf = gst_buffer_new ();
676 GST_BUFFER_SIZE (buf) = size;
678 if (size != 0) {
679 switch (src->filltype) {
680 case FAKE_SRC_FILLTYPE_NOTHING:
681 GST_BUFFER_DATA (buf) = g_malloc (size);
682 GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
683 break;
684 case FAKE_SRC_FILLTYPE_ZERO:
685 GST_BUFFER_DATA (buf) = g_malloc0 (size);
686 GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
687 break;
688 case FAKE_SRC_FILLTYPE_RANDOM:
689 case FAKE_SRC_FILLTYPE_PATTERN:
690 case FAKE_SRC_FILLTYPE_PATTERN_CONT:
691 default:
692 GST_BUFFER_DATA (buf) = g_malloc (size);
693 GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
694 gst_fake_src_prepare_buffer (src, buf);
695 break;
696 }
697 }
699 return buf;
700 }
702 static guint
703 gst_fake_src_get_size (GstFakeSrc * src)
704 {
705 guint size;
707 switch (src->sizetype) {
708 case FAKE_SRC_SIZETYPE_FIXED:
709 size = src->sizemax;
710 break;
711 case FAKE_SRC_SIZETYPE_RANDOM:
712 size = g_random_int_range (src->sizemin, src->sizemax);
713 break;
714 case FAKE_SRC_SIZETYPE_EMPTY:
715 default:
716 size = 0;
717 break;
718 }
720 return size;
721 }
723 static GstBuffer *
724 gst_fake_src_create_buffer (GstFakeSrc * src)
725 {
726 GstBuffer *buf;
727 guint size = gst_fake_src_get_size (src);
728 gboolean dump = src->dump;
730 switch (src->data) {
731 case FAKE_SRC_DATA_ALLOCATE:
732 buf = gst_fake_src_alloc_buffer (src, size);
733 break;
734 case FAKE_SRC_DATA_SUBBUFFER:
735 /* see if we have a parent to subbuffer */
736 if (!src->parent) {
737 gst_fake_src_alloc_parent (src);
738 g_assert (src->parent);
739 }
740 /* see if it's large enough */
741 if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
742 buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
743 src->parentoffset += size;
744 } else {
745 /* the parent is useless now */
746 gst_buffer_unref (src->parent);
747 src->parent = NULL;
748 /* try again (this will allocate a new parent) */
749 return gst_fake_src_create_buffer (src);
750 }
751 gst_fake_src_prepare_buffer (src, buf);
752 break;
753 default:
754 g_warning ("fakesrc: dunno how to allocate buffers !");
755 buf = gst_buffer_new ();
756 break;
757 }
758 if (dump) {
759 gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
760 }
762 return buf;
763 }
765 static void
766 gst_fake_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
767 GstClockTime * start, GstClockTime * end)
768 {
769 GstFakeSrc *src;
771 src = GST_FAKE_SRC (basesrc);
773 /* sync on the timestamp of the buffer if requested. */
774 if (src->sync) {
775 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
777 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
778 /* get duration to calculate end time */
779 GstClockTime duration = GST_BUFFER_DURATION (buffer);
781 if (GST_CLOCK_TIME_IS_VALID (duration)) {
782 *end = timestamp + duration;
783 }
784 *start = timestamp;
785 }
786 } else {
787 *start = -1;
788 *end = -1;
789 }
790 }
792 static GstFlowReturn
793 gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
794 GstBuffer ** ret)
795 {
796 GstFakeSrc *src;
797 GstBuffer *buf;
798 GstClockTime time;
800 src = GST_FAKE_SRC (basesrc);
802 buf = gst_fake_src_create_buffer (src);
803 GST_BUFFER_OFFSET (buf) = src->buffer_count++;
805 if (src->datarate > 0) {
806 time = (src->bytes_sent * GST_SECOND) / src->datarate;
808 GST_BUFFER_DURATION (buf) =
809 GST_BUFFER_SIZE (buf) * GST_SECOND / src->datarate;
810 } else if (gst_base_src_is_live (basesrc)) {
811 GstClock *clock;
813 clock = gst_element_get_clock (GST_ELEMENT (src));
815 if (clock) {
816 time = gst_clock_get_time (clock);
817 time -= gst_element_get_base_time (GST_ELEMENT (src));
818 gst_object_unref (clock);
819 } else {
820 /* not an error not to have a clock */
821 time = GST_CLOCK_TIME_NONE;
822 }
823 } else {
824 time = GST_CLOCK_TIME_NONE;
825 }
827 GST_BUFFER_TIMESTAMP (buf) = time;
829 if (!src->silent) {
830 gchar ts_str[64], dur_str[64];
831 gchar flag_str[100];
833 GST_OBJECT_LOCK (src);
834 g_free (src->last_message);
836 if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) {
837 g_snprintf (ts_str, sizeof (ts_str), "%" GST_TIME_FORMAT,
838 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
839 } else {
840 g_strlcpy (ts_str, "none", sizeof (ts_str));
841 }
843 if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) {
844 g_snprintf (dur_str, sizeof (dur_str), "%" GST_TIME_FORMAT,
845 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
846 } else {
847 g_strlcpy (dur_str, "none", sizeof (dur_str));
848 }
850 {
851 const char *flag_list[12] = {
852 "ro", "media4", "", "",
853 "preroll", "discont", "incaps", "gap",
854 "delta_unit", "media1", "media2", "media3"
855 };
856 int i;
857 char *end = flag_str;
858 end[0] = '\0';
859 for (i = 0; i < 12; i++) {
860 if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) {
861 strcpy (end, flag_list[i]);
862 end += strlen (end);
863 end[0] = ' ';
864 end[1] = '\0';
865 end++;
866 }
867 }
868 }
870 src->last_message =
871 g_strdup_printf ("create ******* (%s:%s) (%u bytes, timestamp: %s"
872 ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %"
873 G_GINT64_FORMAT ", flags: %d %s) %p",
874 GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad),
875 GST_BUFFER_SIZE (buf), ts_str, dur_str, GST_BUFFER_OFFSET (buf),
876 GST_BUFFER_OFFSET_END (buf), GST_MINI_OBJECT (buf)->flags, flag_str,
877 buf);
878 GST_OBJECT_UNLOCK (src);
880 #if !GLIB_CHECK_VERSION(2,26,0)
881 g_object_notify ((GObject *) src, "last-message");
882 #else
883 g_object_notify_by_pspec ((GObject *) src, pspec_last_message);
884 #endif
885 }
887 if (src->signal_handoffs) {
888 GST_LOG_OBJECT (src, "pre handoff emit");
889 g_signal_emit (src, gst_fake_src_signals[SIGNAL_HANDOFF], 0, buf,
890 basesrc->srcpad);
891 GST_LOG_OBJECT (src, "post handoff emit");
892 }
894 src->bytes_sent += GST_BUFFER_SIZE (buf);
896 *ret = buf;
897 return GST_FLOW_OK;
898 }
900 static gboolean
901 gst_fake_src_start (GstBaseSrc * basesrc)
902 {
903 GstFakeSrc *src;
905 src = GST_FAKE_SRC (basesrc);
907 src->buffer_count = 0;
908 src->pattern_byte = 0x00;
909 src->bytes_sent = 0;
911 gst_base_src_set_format (basesrc, src->format);
913 return TRUE;
914 }
916 static gboolean
917 gst_fake_src_stop (GstBaseSrc * basesrc)
918 {
919 GstFakeSrc *src;
921 src = GST_FAKE_SRC (basesrc);
923 GST_OBJECT_LOCK (src);
924 if (src->parent) {
925 gst_buffer_unref (src->parent);
926 src->parent = NULL;
927 }
928 g_free (src->last_message);
929 src->last_message = NULL;
930 GST_OBJECT_UNLOCK (src);
932 return TRUE;
933 }
935 static gboolean
936 gst_fake_src_is_seekable (GstBaseSrc * basesrc)
937 {
938 GstFakeSrc *src = GST_FAKE_SRC (basesrc);
940 return src->can_activate_pull;
941 }