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