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 ******* E (type: %d, %s) %p",
449 GST_EVENT_TYPE (event), sstr, event);
450 g_free (sstr);
451 GST_OBJECT_UNLOCK (src);
453 #if !GLIB_CHECK_VERSION(2,26,0)
454 g_object_notify ((GObject *) src, "last-message");
455 #else
456 g_object_notify_by_pspec ((GObject *) src, pspec_last_message);
457 #endif
458 }
460 return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event);
461 }
463 static void
464 gst_fake_src_alloc_parent (GstFakeSrc * src)
465 {
466 GstBuffer *buf;
468 buf = gst_buffer_new ();
469 GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
470 GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
471 GST_BUFFER_SIZE (buf) = src->parentsize;
473 src->parent = buf;
474 src->parentoffset = 0;
475 }
477 static void
478 gst_fake_src_set_property (GObject * object, guint prop_id,
479 const GValue * value, GParamSpec * pspec)
480 {
481 GstFakeSrc *src;
482 GstBaseSrc *basesrc;
484 src = GST_FAKE_SRC (object);
485 basesrc = GST_BASE_SRC (object);
487 switch (prop_id) {
488 case PROP_OUTPUT:
489 g_warning ("not yet implemented");
490 break;
491 case PROP_DATA:
492 src->data = g_value_get_enum (value);
494 if (src->data == FAKE_SRC_DATA_SUBBUFFER) {
495 if (!src->parent)
496 gst_fake_src_alloc_parent (src);
497 } else {
498 if (src->parent) {
499 gst_buffer_unref (src->parent);
500 src->parent = NULL;
501 }
502 }
503 break;
504 case PROP_SIZETYPE:
505 src->sizetype = g_value_get_enum (value);
506 break;
507 case PROP_SIZEMIN:
508 src->sizemin = g_value_get_int (value);
509 break;
510 case PROP_SIZEMAX:
511 src->sizemax = g_value_get_int (value);
512 break;
513 case PROP_PARENTSIZE:
514 src->parentsize = g_value_get_int (value);
515 break;
516 case PROP_FILLTYPE:
517 src->filltype = g_value_get_enum (value);
518 break;
519 case PROP_DATARATE:
520 src->datarate = g_value_get_int (value);
521 break;
522 case PROP_SYNC:
523 src->sync = g_value_get_boolean (value);
524 break;
525 case PROP_PATTERN:
526 break;
527 case PROP_SILENT:
528 src->silent = g_value_get_boolean (value);
529 break;
530 case PROP_SIGNAL_HANDOFFS:
531 src->signal_handoffs = g_value_get_boolean (value);
532 break;
533 case PROP_DUMP:
534 src->dump = g_value_get_boolean (value);
535 break;
536 case PROP_CAN_ACTIVATE_PUSH:
537 g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
538 GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
539 break;
540 case PROP_CAN_ACTIVATE_PULL:
541 g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
542 src->can_activate_pull = g_value_get_boolean (value);
543 break;
544 case PROP_IS_LIVE:
545 gst_base_src_set_live (basesrc, g_value_get_boolean (value));
546 break;
547 case PROP_FORMAT:
548 src->format = g_value_get_enum (value);
549 break;
550 default:
551 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
552 break;
553 }
554 }
556 static void
557 gst_fake_src_get_property (GObject * object, guint prop_id, GValue * value,
558 GParamSpec * pspec)
559 {
560 GstFakeSrc *src;
561 GstBaseSrc *basesrc;
563 g_return_if_fail (GST_IS_FAKE_SRC (object));
565 src = GST_FAKE_SRC (object);
566 basesrc = GST_BASE_SRC (object);
568 switch (prop_id) {
569 case PROP_OUTPUT:
570 g_value_set_enum (value, src->output);
571 break;
572 case PROP_DATA:
573 g_value_set_enum (value, src->data);
574 break;
575 case PROP_SIZETYPE:
576 g_value_set_enum (value, src->sizetype);
577 break;
578 case PROP_SIZEMIN:
579 g_value_set_int (value, src->sizemin);
580 break;
581 case PROP_SIZEMAX:
582 g_value_set_int (value, src->sizemax);
583 break;
584 case PROP_PARENTSIZE:
585 g_value_set_int (value, src->parentsize);
586 break;
587 case PROP_FILLTYPE:
588 g_value_set_enum (value, src->filltype);
589 break;
590 case PROP_DATARATE:
591 g_value_set_int (value, src->datarate);
592 break;
593 case PROP_SYNC:
594 g_value_set_boolean (value, src->sync);
595 break;
596 case PROP_PATTERN:
597 g_value_set_string (value, src->pattern);
598 break;
599 case PROP_SILENT:
600 g_value_set_boolean (value, src->silent);
601 break;
602 case PROP_SIGNAL_HANDOFFS:
603 g_value_set_boolean (value, src->signal_handoffs);
604 break;
605 case PROP_DUMP:
606 g_value_set_boolean (value, src->dump);
607 break;
608 case PROP_LAST_MESSAGE:
609 GST_OBJECT_LOCK (src);
610 g_value_set_string (value, src->last_message);
611 GST_OBJECT_UNLOCK (src);
612 break;
613 case PROP_CAN_ACTIVATE_PUSH:
614 g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
615 break;
616 case PROP_CAN_ACTIVATE_PULL:
617 g_value_set_boolean (value, src->can_activate_pull);
618 break;
619 case PROP_IS_LIVE:
620 g_value_set_boolean (value, gst_base_src_is_live (basesrc));
621 break;
622 case PROP_FORMAT:
623 g_value_set_enum (value, src->format);
624 break;
625 default:
626 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
627 break;
628 }
629 }
631 static void
632 gst_fake_src_prepare_buffer (GstFakeSrc * src, GstBuffer * buf)
633 {
634 if (GST_BUFFER_SIZE (buf) == 0)
635 return;
637 switch (src->filltype) {
638 case FAKE_SRC_FILLTYPE_ZERO:
639 memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
640 break;
641 case FAKE_SRC_FILLTYPE_RANDOM:
642 {
643 gint i;
644 guint8 *ptr = GST_BUFFER_DATA (buf);
646 for (i = GST_BUFFER_SIZE (buf); i; i--) {
647 *ptr++ = g_random_int_range (0, 256);
648 }
649 break;
650 }
651 case FAKE_SRC_FILLTYPE_PATTERN:
652 src->pattern_byte = 0x00;
653 case FAKE_SRC_FILLTYPE_PATTERN_CONT:
654 {
655 gint i;
656 guint8 *ptr = GST_BUFFER_DATA (buf);
658 for (i = GST_BUFFER_SIZE (buf); i; i--) {
659 *ptr++ = src->pattern_byte++;
660 }
661 break;
662 }
663 case FAKE_SRC_FILLTYPE_NOTHING:
664 default:
665 break;
666 }
667 }
669 static GstBuffer *
670 gst_fake_src_alloc_buffer (GstFakeSrc * src, guint size)
671 {
672 GstBuffer *buf;
674 buf = gst_buffer_new ();
675 GST_BUFFER_SIZE (buf) = size;
677 if (size != 0) {
678 switch (src->filltype) {
679 case FAKE_SRC_FILLTYPE_NOTHING:
680 GST_BUFFER_DATA (buf) = g_malloc (size);
681 GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
682 break;
683 case FAKE_SRC_FILLTYPE_ZERO:
684 GST_BUFFER_DATA (buf) = g_malloc0 (size);
685 GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
686 break;
687 case FAKE_SRC_FILLTYPE_RANDOM:
688 case FAKE_SRC_FILLTYPE_PATTERN:
689 case FAKE_SRC_FILLTYPE_PATTERN_CONT:
690 default:
691 GST_BUFFER_DATA (buf) = g_malloc (size);
692 GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
693 gst_fake_src_prepare_buffer (src, buf);
694 break;
695 }
696 }
698 return buf;
699 }
701 static guint
702 gst_fake_src_get_size (GstFakeSrc * src)
703 {
704 guint size;
706 switch (src->sizetype) {
707 case FAKE_SRC_SIZETYPE_FIXED:
708 size = src->sizemax;
709 break;
710 case FAKE_SRC_SIZETYPE_RANDOM:
711 size = g_random_int_range (src->sizemin, src->sizemax);
712 break;
713 case FAKE_SRC_SIZETYPE_EMPTY:
714 default:
715 size = 0;
716 break;
717 }
719 return size;
720 }
722 static GstBuffer *
723 gst_fake_src_create_buffer (GstFakeSrc * src)
724 {
725 GstBuffer *buf;
726 guint size = gst_fake_src_get_size (src);
727 gboolean dump = src->dump;
729 switch (src->data) {
730 case FAKE_SRC_DATA_ALLOCATE:
731 buf = gst_fake_src_alloc_buffer (src, size);
732 break;
733 case FAKE_SRC_DATA_SUBBUFFER:
734 /* see if we have a parent to subbuffer */
735 if (!src->parent) {
736 gst_fake_src_alloc_parent (src);
737 g_assert (src->parent);
738 }
739 /* see if it's large enough */
740 if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
741 buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
742 src->parentoffset += size;
743 } else {
744 /* the parent is useless now */
745 gst_buffer_unref (src->parent);
746 src->parent = NULL;
747 /* try again (this will allocate a new parent) */
748 return gst_fake_src_create_buffer (src);
749 }
750 gst_fake_src_prepare_buffer (src, buf);
751 break;
752 default:
753 g_warning ("fakesrc: dunno how to allocate buffers !");
754 buf = gst_buffer_new ();
755 break;
756 }
757 if (dump) {
758 gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
759 }
761 return buf;
762 }
764 static void
765 gst_fake_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
766 GstClockTime * start, GstClockTime * end)
767 {
768 GstFakeSrc *src;
770 src = GST_FAKE_SRC (basesrc);
772 /* sync on the timestamp of the buffer if requested. */
773 if (src->sync) {
774 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
776 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
777 /* get duration to calculate end time */
778 GstClockTime duration = GST_BUFFER_DURATION (buffer);
780 if (GST_CLOCK_TIME_IS_VALID (duration)) {
781 *end = timestamp + duration;
782 }
783 *start = timestamp;
784 }
785 } else {
786 *start = -1;
787 *end = -1;
788 }
789 }
791 static GstFlowReturn
792 gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
793 GstBuffer ** ret)
794 {
795 GstFakeSrc *src;
796 GstBuffer *buf;
797 GstClockTime time;
799 src = GST_FAKE_SRC (basesrc);
801 buf = gst_fake_src_create_buffer (src);
802 GST_BUFFER_OFFSET (buf) = src->buffer_count++;
804 if (src->datarate > 0) {
805 time = (src->bytes_sent * GST_SECOND) / src->datarate;
807 GST_BUFFER_DURATION (buf) =
808 GST_BUFFER_SIZE (buf) * GST_SECOND / src->datarate;
809 } else if (gst_base_src_is_live (basesrc)) {
810 GstClock *clock;
812 clock = gst_element_get_clock (GST_ELEMENT (src));
814 if (clock) {
815 time = gst_clock_get_time (clock);
816 time -= gst_element_get_base_time (GST_ELEMENT (src));
817 gst_object_unref (clock);
818 } else {
819 /* not an error not to have a clock */
820 time = GST_CLOCK_TIME_NONE;
821 }
822 } else {
823 time = GST_CLOCK_TIME_NONE;
824 }
826 GST_BUFFER_TIMESTAMP (buf) = time;
828 if (!src->silent) {
829 gchar ts_str[64], dur_str[64];
831 GST_OBJECT_LOCK (src);
832 g_free (src->last_message);
834 if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) {
835 g_snprintf (ts_str, sizeof (ts_str), "%" GST_TIME_FORMAT,
836 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
837 } else {
838 g_strlcpy (ts_str, "none", sizeof (ts_str));
839 }
841 if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) {
842 g_snprintf (dur_str, sizeof (dur_str), "%" GST_TIME_FORMAT,
843 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
844 } else {
845 g_strlcpy (dur_str, "none", sizeof (dur_str));
846 }
848 src->last_message =
849 g_strdup_printf ("get ******* > (%5d bytes, timestamp: %s"
850 ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %"
851 G_GINT64_FORMAT ", flags: %d) %p", GST_BUFFER_SIZE (buf), ts_str,
852 dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
853 GST_MINI_OBJECT (buf)->flags, buf);
854 GST_OBJECT_UNLOCK (src);
856 #if !GLIB_CHECK_VERSION(2,26,0)
857 g_object_notify ((GObject *) src, "last-message");
858 #else
859 g_object_notify_by_pspec ((GObject *) src, pspec_last_message);
860 #endif
861 }
863 if (src->signal_handoffs) {
864 GST_LOG_OBJECT (src, "pre handoff emit");
865 g_signal_emit (src, gst_fake_src_signals[SIGNAL_HANDOFF], 0, buf,
866 basesrc->srcpad);
867 GST_LOG_OBJECT (src, "post handoff emit");
868 }
870 src->bytes_sent += GST_BUFFER_SIZE (buf);
872 *ret = buf;
873 return GST_FLOW_OK;
874 }
876 static gboolean
877 gst_fake_src_start (GstBaseSrc * basesrc)
878 {
879 GstFakeSrc *src;
881 src = GST_FAKE_SRC (basesrc);
883 src->buffer_count = 0;
884 src->pattern_byte = 0x00;
885 src->bytes_sent = 0;
887 gst_base_src_set_format (basesrc, src->format);
889 return TRUE;
890 }
892 static gboolean
893 gst_fake_src_stop (GstBaseSrc * basesrc)
894 {
895 GstFakeSrc *src;
897 src = GST_FAKE_SRC (basesrc);
899 GST_OBJECT_LOCK (src);
900 if (src->parent) {
901 gst_buffer_unref (src->parent);
902 src->parent = NULL;
903 }
904 g_free (src->last_message);
905 src->last_message = NULL;
906 GST_OBJECT_UNLOCK (src);
908 return TRUE;
909 }
911 static gboolean
912 gst_fake_src_is_seekable (GstBaseSrc * basesrc)
913 {
914 GstFakeSrc *src = GST_FAKE_SRC (basesrc);
916 return src->can_activate_pull;
917 }