2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2005 Wim Taymans <wim@fluendo.com>
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.
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.
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.
25 #include "gstbaseaudiosrc.h"
27 GST_DEBUG_CATEGORY_STATIC (gst_base_audio_src_debug);
28 #define GST_CAT_DEFAULT gst_base_audio_src_debug
30 /* BaseAudioSrc signals and args */
37 #define DEFAULT_BUFFER_TIME 500 * GST_USECOND
38 #define DEFAULT_LATENCY_TIME 10 * GST_USECOND
46 #define _do_init(bla) \
47 GST_DEBUG_CATEGORY_INIT (gst_base_audio_src_debug, "baseaudiosrc", 0, "baseaudiosrc element");
49 GST_BOILERPLATE_FULL (GstBaseAudioSrc, gst_base_audio_src, GstPushSrc,
50 GST_TYPE_PUSH_SRC, _do_init);
52 static void gst_base_audio_src_set_property (GObject * object, guint prop_id,
53 const GValue * value, GParamSpec * pspec);
54 static void gst_base_audio_src_get_property (GObject * object, guint prop_id,
55 GValue * value, GParamSpec * pspec);
57 static void gst_base_audio_src_fixate (GstPad * pad, GstCaps * caps);
59 static GstStateChangeReturn gst_base_audio_src_change_state (GstElement *
60 element, GstStateChange transition);
62 static GstClock *gst_base_audio_src_provide_clock (GstElement * elem);
63 static GstClockTime gst_base_audio_src_get_time (GstClock * clock,
64 GstBaseAudioSrc * src);
66 static GstFlowReturn gst_base_audio_src_create (GstPushSrc * psrc,
69 static gboolean gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event);
70 static void gst_base_audio_src_get_times (GstBaseSrc * bsrc,
71 GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
72 static gboolean gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
74 //static guint gst_base_audio_src_signals[LAST_SIGNAL] = { 0 };
77 gst_base_audio_src_base_init (gpointer g_class)
82 gst_base_audio_src_class_init (GstBaseAudioSrcClass * klass)
84 GObjectClass *gobject_class;
85 GstElementClass *gstelement_class;
86 GstBaseSrcClass *gstbasesrc_class;
87 GstPushSrcClass *gstpushsrc_class;
89 gobject_class = (GObjectClass *) klass;
90 gstelement_class = (GstElementClass *) klass;
91 gstbasesrc_class = (GstBaseSrcClass *) klass;
92 gstpushsrc_class = (GstPushSrcClass *) klass;
94 gobject_class->set_property =
95 GST_DEBUG_FUNCPTR (gst_base_audio_src_set_property);
96 gobject_class->get_property =
97 GST_DEBUG_FUNCPTR (gst_base_audio_src_get_property);
99 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFFER_TIME,
100 g_param_spec_int64 ("buffer-time", "Buffer Time",
101 "Size of audio buffer in milliseconds (-1 = default)",
102 -1, G_MAXINT64, DEFAULT_BUFFER_TIME, G_PARAM_READWRITE));
103 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LATENCY_TIME,
104 g_param_spec_int64 ("latency-time", "Latency Time",
105 "Audio latency in milliseconds (-1 = default)",
106 -1, G_MAXINT64, DEFAULT_LATENCY_TIME, G_PARAM_READWRITE));
108 gstelement_class->change_state =
109 GST_DEBUG_FUNCPTR (gst_base_audio_src_change_state);
110 gstelement_class->provide_clock =
111 GST_DEBUG_FUNCPTR (gst_base_audio_src_provide_clock);
113 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_base_audio_src_setcaps);
114 gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_src_event);
115 gstbasesrc_class->get_times =
116 GST_DEBUG_FUNCPTR (gst_base_audio_src_get_times);
118 gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_base_audio_src_create);
122 gst_base_audio_src_init (GstBaseAudioSrc * baseaudiosrc,
123 GstBaseAudioSrcClass * g_class)
125 baseaudiosrc->buffer_time = DEFAULT_BUFFER_TIME;
126 baseaudiosrc->latency_time = DEFAULT_LATENCY_TIME;
128 baseaudiosrc->clock = gst_audio_clock_new ("clock",
129 (GstAudioClockGetTimeFunc) gst_base_audio_src_get_time, baseaudiosrc);
131 gst_pad_set_fixatecaps_function (GST_BASE_SRC_PAD (baseaudiosrc),
132 gst_base_audio_src_fixate);
136 gst_base_audio_src_provide_clock (GstElement * elem)
138 GstBaseAudioSrc *src;
140 src = GST_BASE_AUDIO_SRC (elem);
142 return GST_CLOCK (gst_object_ref (GST_OBJECT (src->clock)));
146 gst_base_audio_src_get_time (GstClock * clock, GstBaseAudioSrc * src)
151 if (src->ringbuffer == NULL || src->ringbuffer->spec.rate == 0)
154 samples = gst_ring_buffer_samples_done (src->ringbuffer);
156 result = samples * GST_SECOND / src->ringbuffer->spec.rate;
162 gst_base_audio_src_set_property (GObject * object, guint prop_id,
163 const GValue * value, GParamSpec * pspec)
165 GstBaseAudioSrc *src;
167 src = GST_BASE_AUDIO_SRC (object);
170 case PROP_BUFFER_TIME:
171 src->buffer_time = g_value_get_int64 (value);
173 case PROP_LATENCY_TIME:
174 src->latency_time = g_value_get_int64 (value);
177 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
183 gst_base_audio_src_get_property (GObject * object, guint prop_id,
184 GValue * value, GParamSpec * pspec)
186 GstBaseAudioSrc *src;
188 src = GST_BASE_AUDIO_SRC (object);
191 case PROP_BUFFER_TIME:
192 g_value_set_int64 (value, src->buffer_time);
194 case PROP_LATENCY_TIME:
195 g_value_set_int64 (value, src->latency_time);
198 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
204 gst_base_audio_src_fixate (GstPad * pad, GstCaps * caps)
208 s = gst_caps_get_structure (caps, 0);
210 gst_structure_fixate_field_nearest_int (s, "rate", 44100);
211 gst_structure_fixate_field_nearest_int (s, "channels", 2);
212 gst_structure_fixate_field_nearest_int (s, "depth", 16);
213 gst_structure_fixate_field_nearest_int (s, "width", 16);
214 gst_structure_set (s, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
215 if (gst_structure_has_field (s, "endianness"))
216 gst_structure_fixate_field_nearest_int (s, "endianness", G_BYTE_ORDER);
220 gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
222 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
223 GstRingBufferSpec *spec;
225 spec = &src->ringbuffer->spec;
227 spec->buffer_time = src->buffer_time;
228 spec->latency_time = src->latency_time;
230 if (!gst_ring_buffer_parse_caps (spec, caps))
233 /* calculate suggested segsize and segtotal */
235 spec->rate * spec->bytes_per_sample * spec->latency_time / GST_MSECOND;
236 spec->segtotal = spec->buffer_time / spec->latency_time;
238 GST_DEBUG ("release old ringbuffer");
240 gst_ring_buffer_release (src->ringbuffer);
242 gst_ring_buffer_debug_spec_buff (spec);
244 GST_DEBUG ("acquire new ringbuffer");
246 if (!gst_ring_buffer_acquire (src->ringbuffer, spec))
249 /* calculate actual latency and buffer times */
251 spec->segsize * GST_MSECOND / (spec->rate * spec->bytes_per_sample);
253 spec->segtotal * spec->segsize * GST_MSECOND / (spec->rate *
254 spec->bytes_per_sample);
256 gst_ring_buffer_debug_spec_buff (spec);
263 GST_DEBUG ("could not parse caps");
268 GST_DEBUG ("could not acquire ringbuffer");
274 gst_base_audio_src_get_times (GstBaseSrc * bsrc, GstBuffer * buffer,
275 GstClockTime * start, GstClockTime * end)
277 /* ne need to sync to a clock here, we schedule the samples based
278 * on our own clock for the moment. FIXME, implement this when
279 * we are not using our own clock */
280 *start = GST_CLOCK_TIME_NONE;
281 *end = GST_CLOCK_TIME_NONE;
285 gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event)
287 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
289 switch (GST_EVENT_TYPE (event)) {
290 case GST_EVENT_FLUSH_START:
291 gst_ring_buffer_pause (src->ringbuffer);
292 gst_ring_buffer_clear_all (src->ringbuffer);
294 case GST_EVENT_FLUSH_STOP:
295 /* always resync on sample after a flush */
296 src->next_sample = -1;
297 gst_ring_buffer_clear_all (src->ringbuffer);
306 gst_base_audio_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
308 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (psrc);
315 if (!gst_ring_buffer_is_acquired (src->ringbuffer))
318 buf = gst_buffer_new_and_alloc (src->ringbuffer->spec.segsize);
320 data = GST_BUFFER_DATA (buf);
321 len = GST_BUFFER_SIZE (buf);
323 if (src->next_sample != -1) {
324 sample = src->next_sample;
329 samples = len / src->ringbuffer->spec.bytes_per_sample;
331 res = gst_ring_buffer_read (src->ringbuffer, sample, data, samples);
335 src->next_sample = sample + samples;
337 gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc)));
345 GST_DEBUG ("ringbuffer in wrong state");
346 return GST_FLOW_WRONG_STATE;
350 gst_buffer_unref (buf);
351 GST_DEBUG ("ringbuffer stopped");
352 return GST_FLOW_WRONG_STATE;
357 gst_base_audio_src_create_ringbuffer (GstBaseAudioSrc * src)
359 GstBaseAudioSrcClass *bclass;
360 GstRingBuffer *buffer = NULL;
362 bclass = GST_BASE_AUDIO_SRC_GET_CLASS (src);
363 if (bclass->create_ringbuffer)
364 buffer = bclass->create_ringbuffer (src);
367 gst_object_set_parent (GST_OBJECT (buffer), GST_OBJECT (src));
374 gst_base_audio_src_callback (GstRingBuffer * rbuf, guint8 * data, guint len,
377 //GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (data);
380 static GstStateChangeReturn
381 gst_base_audio_src_change_state (GstElement * element,
382 GstStateChange transition)
384 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
385 GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (element);
387 switch (transition) {
388 case GST_STATE_CHANGE_NULL_TO_READY:
389 if (src->ringbuffer == NULL) {
390 src->ringbuffer = gst_base_audio_src_create_ringbuffer (src);
391 gst_ring_buffer_set_callback (src->ringbuffer,
392 gst_base_audio_src_callback, src);
394 if (!gst_ring_buffer_open_device (src->ringbuffer))
395 return GST_STATE_CHANGE_FAILURE;
396 src->next_sample = 0;
398 case GST_STATE_CHANGE_READY_TO_PAUSED:
399 gst_ring_buffer_set_flushing (src->ringbuffer, FALSE);
401 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
407 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
409 switch (transition) {
410 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
411 gst_ring_buffer_pause (src->ringbuffer);
413 case GST_STATE_CHANGE_PAUSED_TO_READY:
414 gst_ring_buffer_set_flushing (src->ringbuffer, TRUE);
415 gst_ring_buffer_release (src->ringbuffer);
416 src->next_sample = 0;
418 case GST_STATE_CHANGE_READY_TO_NULL:
419 gst_ring_buffer_close_device (src->ringbuffer);
420 gst_object_unref (src->ringbuffer);
421 src->ringbuffer = NULL;