expand tabs
[platform/upstream/gstreamer.git] / gst-libs / gst / audio / gstbaseaudiosrc.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2005 Wim Taymans <wim@fluendo.com>
4  *
5  * gstbaseaudiosrc.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 #include <string.h>
24
25 #include "gstbaseaudiosrc.h"
26
27 GST_DEBUG_CATEGORY_STATIC (gst_base_audio_src_debug);
28 #define GST_CAT_DEFAULT gst_base_audio_src_debug
29
30 /* BaseAudioSrc signals and args */
31 enum
32 {
33   /* FILL ME */
34   LAST_SIGNAL
35 };
36
37 #define DEFAULT_BUFFER_TIME     500 * GST_USECOND
38 #define DEFAULT_LATENCY_TIME    10 * GST_USECOND
39 enum
40 {
41   PROP_0,
42   PROP_BUFFER_TIME,
43   PROP_LATENCY_TIME,
44 };
45
46 #define _do_init(bla) \
47     GST_DEBUG_CATEGORY_INIT (gst_base_audio_src_debug, "baseaudiosrc", 0, "baseaudiosrc element");
48
49 GST_BOILERPLATE_FULL (GstBaseAudioSrc, gst_base_audio_src, GstPushSrc,
50     GST_TYPE_PUSH_SRC, _do_init);
51
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);
56
57 static void gst_base_audio_src_fixate (GstPad * pad, GstCaps * caps);
58
59 static GstStateChangeReturn gst_base_audio_src_change_state (GstElement *
60     element, GstStateChange transition);
61
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);
65
66 static GstFlowReturn gst_base_audio_src_create (GstPushSrc * psrc,
67     GstBuffer ** buf);
68
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);
73
74 //static guint gst_base_audio_src_signals[LAST_SIGNAL] = { 0 };
75
76 static void
77 gst_base_audio_src_base_init (gpointer g_class)
78 {
79 }
80
81 static void
82 gst_base_audio_src_class_init (GstBaseAudioSrcClass * klass)
83 {
84   GObjectClass *gobject_class;
85   GstElementClass *gstelement_class;
86   GstBaseSrcClass *gstbasesrc_class;
87   GstPushSrcClass *gstpushsrc_class;
88
89   gobject_class = (GObjectClass *) klass;
90   gstelement_class = (GstElementClass *) klass;
91   gstbasesrc_class = (GstBaseSrcClass *) klass;
92   gstpushsrc_class = (GstPushSrcClass *) klass;
93
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);
98
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));
107
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);
112
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);
117
118   gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_base_audio_src_create);
119 }
120
121 static void
122 gst_base_audio_src_init (GstBaseAudioSrc * baseaudiosrc,
123     GstBaseAudioSrcClass * g_class)
124 {
125   baseaudiosrc->buffer_time = DEFAULT_BUFFER_TIME;
126   baseaudiosrc->latency_time = DEFAULT_LATENCY_TIME;
127
128   baseaudiosrc->clock = gst_audio_clock_new ("clock",
129       (GstAudioClockGetTimeFunc) gst_base_audio_src_get_time, baseaudiosrc);
130
131   gst_pad_set_fixatecaps_function (GST_BASE_SRC_PAD (baseaudiosrc),
132       gst_base_audio_src_fixate);
133 }
134
135 static GstClock *
136 gst_base_audio_src_provide_clock (GstElement * elem)
137 {
138   GstBaseAudioSrc *src;
139
140   src = GST_BASE_AUDIO_SRC (elem);
141
142   return GST_CLOCK (gst_object_ref (GST_OBJECT (src->clock)));
143 }
144
145 static GstClockTime
146 gst_base_audio_src_get_time (GstClock * clock, GstBaseAudioSrc * src)
147 {
148   guint64 samples;
149   GstClockTime result;
150
151   if (src->ringbuffer == NULL || src->ringbuffer->spec.rate == 0)
152     return 0;
153
154   samples = gst_ring_buffer_samples_done (src->ringbuffer);
155
156   result = samples * GST_SECOND / src->ringbuffer->spec.rate;
157
158   return result;
159 }
160
161 static void
162 gst_base_audio_src_set_property (GObject * object, guint prop_id,
163     const GValue * value, GParamSpec * pspec)
164 {
165   GstBaseAudioSrc *src;
166
167   src = GST_BASE_AUDIO_SRC (object);
168
169   switch (prop_id) {
170     case PROP_BUFFER_TIME:
171       src->buffer_time = g_value_get_int64 (value);
172       break;
173     case PROP_LATENCY_TIME:
174       src->latency_time = g_value_get_int64 (value);
175       break;
176     default:
177       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
178       break;
179   }
180 }
181
182 static void
183 gst_base_audio_src_get_property (GObject * object, guint prop_id,
184     GValue * value, GParamSpec * pspec)
185 {
186   GstBaseAudioSrc *src;
187
188   src = GST_BASE_AUDIO_SRC (object);
189
190   switch (prop_id) {
191     case PROP_BUFFER_TIME:
192       g_value_set_int64 (value, src->buffer_time);
193       break;
194     case PROP_LATENCY_TIME:
195       g_value_set_int64 (value, src->latency_time);
196       break;
197     default:
198       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
199       break;
200   }
201 }
202
203 static void
204 gst_base_audio_src_fixate (GstPad * pad, GstCaps * caps)
205 {
206   GstStructure *s;
207
208   s = gst_caps_get_structure (caps, 0);
209
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);
217 }
218
219 static gboolean
220 gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
221 {
222   GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
223   GstRingBufferSpec *spec;
224
225   spec = &src->ringbuffer->spec;
226
227   spec->buffer_time = src->buffer_time;
228   spec->latency_time = src->latency_time;
229
230   if (!gst_ring_buffer_parse_caps (spec, caps))
231     goto parse_error;
232
233   /* calculate suggested segsize and segtotal */
234   spec->segsize =
235       spec->rate * spec->bytes_per_sample * spec->latency_time / GST_MSECOND;
236   spec->segtotal = spec->buffer_time / spec->latency_time;
237
238   GST_DEBUG ("release old ringbuffer");
239
240   gst_ring_buffer_release (src->ringbuffer);
241
242   gst_ring_buffer_debug_spec_buff (spec);
243
244   GST_DEBUG ("acquire new ringbuffer");
245
246   if (!gst_ring_buffer_acquire (src->ringbuffer, spec))
247     goto acquire_error;
248
249   /* calculate actual latency and buffer times */
250   spec->latency_time =
251       spec->segsize * GST_MSECOND / (spec->rate * spec->bytes_per_sample);
252   spec->buffer_time =
253       spec->segtotal * spec->segsize * GST_MSECOND / (spec->rate *
254       spec->bytes_per_sample);
255
256   gst_ring_buffer_debug_spec_buff (spec);
257
258   return TRUE;
259
260   /* ERRORS */
261 parse_error:
262   {
263     GST_DEBUG ("could not parse caps");
264     return FALSE;
265   }
266 acquire_error:
267   {
268     GST_DEBUG ("could not acquire ringbuffer");
269     return FALSE;
270   }
271 }
272
273 static void
274 gst_base_audio_src_get_times (GstBaseSrc * bsrc, GstBuffer * buffer,
275     GstClockTime * start, GstClockTime * end)
276 {
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;
282 }
283
284 static gboolean
285 gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event)
286 {
287   GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
288
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);
293       break;
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);
298       break;
299     default:
300       break;
301   }
302   return TRUE;
303 }
304
305 static GstFlowReturn
306 gst_base_audio_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
307 {
308   GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (psrc);
309   GstBuffer *buf;
310   guchar *data;
311   guint len, samples;
312   guint res;
313   guint64 sample;
314
315   if (!gst_ring_buffer_is_acquired (src->ringbuffer))
316     goto wrong_state;
317
318   buf = gst_buffer_new_and_alloc (src->ringbuffer->spec.segsize);
319
320   data = GST_BUFFER_DATA (buf);
321   len = GST_BUFFER_SIZE (buf);
322
323   if (src->next_sample != -1) {
324     sample = src->next_sample;
325   } else {
326     sample = 0;
327   }
328
329   samples = len / src->ringbuffer->spec.bytes_per_sample;
330
331   res = gst_ring_buffer_read (src->ringbuffer, sample, data, samples);
332   if (res == -1)
333     goto stopped;
334
335   src->next_sample = sample + samples;
336
337   gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc)));
338
339   *outbuf = buf;
340
341   return GST_FLOW_OK;
342
343 wrong_state:
344   {
345     GST_DEBUG ("ringbuffer in wrong state");
346     return GST_FLOW_WRONG_STATE;
347   }
348 stopped:
349   {
350     gst_buffer_unref (buf);
351     GST_DEBUG ("ringbuffer stopped");
352     return GST_FLOW_WRONG_STATE;
353   }
354 }
355
356 GstRingBuffer *
357 gst_base_audio_src_create_ringbuffer (GstBaseAudioSrc * src)
358 {
359   GstBaseAudioSrcClass *bclass;
360   GstRingBuffer *buffer = NULL;
361
362   bclass = GST_BASE_AUDIO_SRC_GET_CLASS (src);
363   if (bclass->create_ringbuffer)
364     buffer = bclass->create_ringbuffer (src);
365
366   if (buffer) {
367     gst_object_set_parent (GST_OBJECT (buffer), GST_OBJECT (src));
368   }
369
370   return buffer;
371 }
372
373 void
374 gst_base_audio_src_callback (GstRingBuffer * rbuf, guint8 * data, guint len,
375     gpointer user_data)
376 {
377   //GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (data);
378 }
379
380 static GstStateChangeReturn
381 gst_base_audio_src_change_state (GstElement * element,
382     GstStateChange transition)
383 {
384   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
385   GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (element);
386
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);
393       }
394       if (!gst_ring_buffer_open_device (src->ringbuffer))
395         return GST_STATE_CHANGE_FAILURE;
396       src->next_sample = 0;
397       break;
398     case GST_STATE_CHANGE_READY_TO_PAUSED:
399       gst_ring_buffer_set_flushing (src->ringbuffer, FALSE);
400       break;
401     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
402       break;
403     default:
404       break;
405   }
406
407   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
408
409   switch (transition) {
410     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
411       gst_ring_buffer_pause (src->ringbuffer);
412       break;
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;
417       break;
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;
422       break;
423     default:
424       break;
425   }
426
427   return ret;
428 }