|
1 /* GStreamer |
|
2 * Copyright (C) 2005 Wim Taymans <wim@fluendo.com> |
|
3 * |
|
4 * This library is free software; you can redistribute it and/or |
|
5 * modify it under the terms of the GNU Library General Public |
|
6 * License as published by the Free Software Foundation; either |
|
7 * version 2 of the License, or (at your option) any later version. |
|
8 * |
|
9 * This library is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 * Library General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU Library General Public |
|
15 * License along with this library; if not, write to the |
|
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
17 * Boston, MA 02111-1307, USA. |
|
18 */ |
|
19 |
|
20 /** |
|
21 * SECTION:gstringbuffer |
|
22 * @short_description: Base class for audio ringbuffer implementations |
|
23 * @see_also: #GstBaseAudioSink, #GstAudioSink |
|
24 * |
|
25 * <refsect2> |
|
26 * <para> |
|
27 * This object is the base class for audio ringbuffers used by the base |
|
28 * audio source and sink classes. |
|
29 * </para> |
|
30 * <para> |
|
31 * The ringbuffer abstracts a circular buffer of data. One reader and |
|
32 * one writer can operate on the data from different threads in a lockfree |
|
33 * manner. The base class is sufficiently flexible to be used as an |
|
34 * abstraction for DMA based ringbuffers as well as a pure software |
|
35 * implementations. |
|
36 * </para> |
|
37 * </refsect2> |
|
38 * |
|
39 * Last reviewed on 2006-02-02 (0.10.4) |
|
40 */ |
|
41 |
|
42 #include <string.h> |
|
43 |
|
44 #include "gstringbuffer.h" |
|
45 |
|
46 #ifdef __SYMBIAN32__ |
|
47 #include <glib_global.h> |
|
48 #endif |
|
49 |
|
50 GST_DEBUG_CATEGORY_STATIC (gst_ring_buffer_debug); |
|
51 #define GST_CAT_DEFAULT gst_ring_buffer_debug |
|
52 |
|
53 static void gst_ring_buffer_class_init (GstRingBufferClass * klass); |
|
54 static void gst_ring_buffer_init (GstRingBuffer * ringbuffer); |
|
55 static void gst_ring_buffer_dispose (GObject * object); |
|
56 static void gst_ring_buffer_finalize (GObject * object); |
|
57 |
|
58 static gboolean gst_ring_buffer_pause_unlocked (GstRingBuffer * buf); |
|
59 |
|
60 static GstObjectClass *parent_class = NULL; |
|
61 |
|
62 /* ringbuffer abstract base class */ |
|
63 #ifdef __SYMBIAN32__ |
|
64 EXPORT_C |
|
65 #endif |
|
66 |
|
67 GType |
|
68 gst_ring_buffer_get_type (void) |
|
69 { |
|
70 static GType ringbuffer_type = 0; |
|
71 |
|
72 if (G_UNLIKELY (!ringbuffer_type)) { |
|
73 static const GTypeInfo ringbuffer_info = { |
|
74 sizeof (GstRingBufferClass), |
|
75 NULL, |
|
76 NULL, |
|
77 (GClassInitFunc) gst_ring_buffer_class_init, |
|
78 NULL, |
|
79 NULL, |
|
80 sizeof (GstRingBuffer), |
|
81 0, |
|
82 (GInstanceInitFunc) gst_ring_buffer_init, |
|
83 NULL |
|
84 }; |
|
85 |
|
86 ringbuffer_type = g_type_register_static (GST_TYPE_OBJECT, "GstRingBuffer", |
|
87 &ringbuffer_info, G_TYPE_FLAG_ABSTRACT); |
|
88 |
|
89 GST_DEBUG_CATEGORY_INIT (gst_ring_buffer_debug, "ringbuffer", 0, |
|
90 "ringbuffer class"); |
|
91 } |
|
92 return ringbuffer_type; |
|
93 } |
|
94 |
|
95 static void |
|
96 gst_ring_buffer_class_init (GstRingBufferClass * klass) |
|
97 { |
|
98 GObjectClass *gobject_class; |
|
99 GstObjectClass *gstobject_class; |
|
100 |
|
101 gobject_class = (GObjectClass *) klass; |
|
102 gstobject_class = (GstObjectClass *) klass; |
|
103 |
|
104 parent_class = g_type_class_peek_parent (klass); |
|
105 |
|
106 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ring_buffer_dispose); |
|
107 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ring_buffer_finalize); |
|
108 } |
|
109 |
|
110 static void |
|
111 gst_ring_buffer_init (GstRingBuffer * ringbuffer) |
|
112 { |
|
113 ringbuffer->open = FALSE; |
|
114 ringbuffer->acquired = FALSE; |
|
115 ringbuffer->state = GST_RING_BUFFER_STATE_STOPPED; |
|
116 ringbuffer->cond = g_cond_new (); |
|
117 ringbuffer->waiting = 0; |
|
118 ringbuffer->empty_seg = NULL; |
|
119 ringbuffer->abidata.ABI.flushing = TRUE; |
|
120 } |
|
121 |
|
122 static void |
|
123 gst_ring_buffer_dispose (GObject * object) |
|
124 { |
|
125 GstRingBuffer *ringbuffer = GST_RING_BUFFER (object); |
|
126 |
|
127 gst_caps_replace (&ringbuffer->spec.caps, NULL); |
|
128 |
|
129 G_OBJECT_CLASS (parent_class)->dispose (G_OBJECT (ringbuffer)); |
|
130 } |
|
131 |
|
132 static void |
|
133 gst_ring_buffer_finalize (GObject * object) |
|
134 { |
|
135 GstRingBuffer *ringbuffer = GST_RING_BUFFER (object); |
|
136 |
|
137 g_cond_free (ringbuffer->cond); |
|
138 g_free (ringbuffer->empty_seg); |
|
139 |
|
140 G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (ringbuffer)); |
|
141 } |
|
142 |
|
143 typedef struct |
|
144 { |
|
145 const GstBufferFormat format; |
|
146 const guint8 silence[4]; |
|
147 } FormatDef; |
|
148 |
|
149 static const FormatDef linear_defs[4 * 2 * 2] = { |
|
150 {GST_S8, {0x00, 0x00, 0x00, 0x00}}, |
|
151 {GST_S8, {0x00, 0x00, 0x00, 0x00}}, |
|
152 {GST_U8, {0x80, 0x80, 0x80, 0x80}}, |
|
153 {GST_U8, {0x80, 0x80, 0x80, 0x80}}, |
|
154 {GST_S16_LE, {0x00, 0x00, 0x00, 0x00}}, |
|
155 {GST_S16_BE, {0x00, 0x00, 0x00, 0x00}}, |
|
156 {GST_U16_LE, {0x00, 0x80, 0x00, 0x80}}, |
|
157 {GST_U16_BE, {0x80, 0x00, 0x80, 0x00}}, |
|
158 {GST_S24_LE, {0x00, 0x00, 0x00, 0x00}}, |
|
159 {GST_S24_BE, {0x00, 0x00, 0x00, 0x00}}, |
|
160 {GST_U24_LE, {0x00, 0x00, 0x80, 0x00}}, |
|
161 {GST_U24_BE, {0x80, 0x00, 0x00, 0x00}}, |
|
162 {GST_S32_LE, {0x00, 0x00, 0x00, 0x00}}, |
|
163 {GST_S32_BE, {0x00, 0x00, 0x00, 0x00}}, |
|
164 {GST_U32_LE, {0x00, 0x00, 0x00, 0x80}}, |
|
165 {GST_U32_BE, {0x80, 0x00, 0x00, 0x00}} |
|
166 }; |
|
167 |
|
168 static const FormatDef linear24_defs[3 * 2 * 2] = { |
|
169 {GST_S24_3LE, {0x00, 0x00, 0x00, 0x00}}, |
|
170 {GST_S24_3BE, {0x00, 0x00, 0x00, 0x00}}, |
|
171 {GST_U24_3LE, {0x00, 0x00, 0x80, 0x00}}, |
|
172 {GST_U24_3BE, {0x80, 0x00, 0x00, 0x00}}, |
|
173 {GST_S20_3LE, {0x00, 0x00, 0x00, 0x00}}, |
|
174 {GST_S20_3BE, {0x00, 0x00, 0x00, 0x00}}, |
|
175 {GST_U20_3LE, {0x00, 0x00, 0x08, 0x00}}, |
|
176 {GST_U20_3BE, {0x08, 0x00, 0x00, 0x00}}, |
|
177 {GST_S18_3LE, {0x00, 0x00, 0x00, 0x00}}, |
|
178 {GST_S18_3BE, {0x00, 0x00, 0x00, 0x00}}, |
|
179 {GST_U18_3LE, {0x00, 0x00, 0x02, 0x00}}, |
|
180 {GST_U18_3BE, {0x02, 0x00, 0x00, 0x00}} |
|
181 }; |
|
182 |
|
183 static const FormatDef * |
|
184 build_linear_format (int depth, int width, int unsignd, int big_endian) |
|
185 { |
|
186 const FormatDef *formats; |
|
187 |
|
188 if (width == 24) { |
|
189 switch (depth) { |
|
190 case 24: |
|
191 formats = &linear24_defs[0]; |
|
192 break; |
|
193 case 20: |
|
194 formats = &linear24_defs[4]; |
|
195 break; |
|
196 case 18: |
|
197 formats = &linear24_defs[8]; |
|
198 break; |
|
199 default: |
|
200 return NULL; |
|
201 } |
|
202 } else { |
|
203 switch (depth) { |
|
204 case 8: |
|
205 formats = &linear_defs[0]; |
|
206 break; |
|
207 case 16: |
|
208 formats = &linear_defs[4]; |
|
209 break; |
|
210 case 24: |
|
211 formats = &linear_defs[8]; |
|
212 break; |
|
213 case 32: |
|
214 formats = &linear_defs[12]; |
|
215 break; |
|
216 default: |
|
217 return NULL; |
|
218 } |
|
219 } |
|
220 if (unsignd) |
|
221 formats += 2; |
|
222 if (big_endian) |
|
223 formats += 1; |
|
224 |
|
225 return formats; |
|
226 } |
|
227 |
|
228 /** |
|
229 * gst_ring_buffer_debug_spec_caps: |
|
230 * @spec: the spec to debug |
|
231 * |
|
232 * Print debug info about the parsed caps in @spec to the debug log. |
|
233 */ |
|
234 #ifdef __SYMBIAN32__ |
|
235 EXPORT_C |
|
236 #endif |
|
237 |
|
238 void |
|
239 gst_ring_buffer_debug_spec_caps (GstRingBufferSpec * spec) |
|
240 { |
|
241 gint i, bytes; |
|
242 |
|
243 GST_DEBUG ("spec caps: %p %" GST_PTR_FORMAT, spec->caps, spec->caps); |
|
244 GST_DEBUG ("parsed caps: type: %d", spec->type); |
|
245 GST_DEBUG ("parsed caps: format: %d", spec->format); |
|
246 GST_DEBUG ("parsed caps: width: %d", spec->width); |
|
247 GST_DEBUG ("parsed caps: depth: %d", spec->depth); |
|
248 GST_DEBUG ("parsed caps: sign: %d", spec->sign); |
|
249 GST_DEBUG ("parsed caps: bigend: %d", spec->bigend); |
|
250 GST_DEBUG ("parsed caps: rate: %d", spec->rate); |
|
251 GST_DEBUG ("parsed caps: channels: %d", spec->channels); |
|
252 GST_DEBUG ("parsed caps: sample bytes: %d", spec->bytes_per_sample); |
|
253 bytes = (spec->width >> 3) * spec->channels; |
|
254 for (i = 0; i < bytes; i++) { |
|
255 GST_DEBUG ("silence byte %d: %02x", i, spec->silence_sample[i]); |
|
256 } |
|
257 } |
|
258 |
|
259 /** |
|
260 * gst_ring_buffer_debug_spec_buff: |
|
261 * @spec: the spec to debug |
|
262 * |
|
263 * Print debug info about the buffer sized in @spec to the debug log. |
|
264 */ |
|
265 #ifdef __SYMBIAN32__ |
|
266 EXPORT_C |
|
267 #endif |
|
268 |
|
269 void |
|
270 gst_ring_buffer_debug_spec_buff (GstRingBufferSpec * spec) |
|
271 { |
|
272 GST_DEBUG ("acquire ringbuffer: buffer time: %" G_GINT64_FORMAT " usec", |
|
273 spec->buffer_time); |
|
274 GST_DEBUG ("acquire ringbuffer: latency time: %" G_GINT64_FORMAT " usec", |
|
275 spec->latency_time); |
|
276 GST_DEBUG ("acquire ringbuffer: total segments: %d", spec->segtotal); |
|
277 GST_DEBUG ("acquire ringbuffer: segment size: %d bytes = %d samples", |
|
278 spec->segsize, spec->segsize / spec->bytes_per_sample); |
|
279 GST_DEBUG ("acquire ringbuffer: buffer size: %d bytes = %d samples", |
|
280 spec->segsize * spec->segtotal, |
|
281 spec->segsize * spec->segtotal / spec->bytes_per_sample); |
|
282 } |
|
283 |
|
284 /** |
|
285 * gst_ring_buffer_parse_caps: |
|
286 * @spec: a spec |
|
287 * @caps: a #GstCaps |
|
288 * |
|
289 * Parse @caps into @spec. |
|
290 * |
|
291 * Returns: TRUE if the caps could be parsed. |
|
292 */ |
|
293 #ifdef __SYMBIAN32__ |
|
294 EXPORT_C |
|
295 #endif |
|
296 |
|
297 gboolean |
|
298 gst_ring_buffer_parse_caps (GstRingBufferSpec * spec, GstCaps * caps) |
|
299 { |
|
300 const gchar *mimetype; |
|
301 GstStructure *structure; |
|
302 gint i; |
|
303 |
|
304 structure = gst_caps_get_structure (caps, 0); |
|
305 |
|
306 /* we have to differentiate between int and float formats */ |
|
307 mimetype = gst_structure_get_name (structure); |
|
308 |
|
309 if (!strncmp (mimetype, "audio/x-raw-int", 15)) { |
|
310 gint endianness; |
|
311 const FormatDef *def; |
|
312 gint j, bytes; |
|
313 |
|
314 spec->type = GST_BUFTYPE_LINEAR; |
|
315 |
|
316 /* extract the needed information from the cap */ |
|
317 if (!(gst_structure_get_int (structure, "rate", &spec->rate) && |
|
318 gst_structure_get_int (structure, "channels", &spec->channels) && |
|
319 gst_structure_get_int (structure, "width", &spec->width) && |
|
320 gst_structure_get_int (structure, "depth", &spec->depth) && |
|
321 gst_structure_get_boolean (structure, "signed", &spec->sign))) |
|
322 goto parse_error; |
|
323 |
|
324 /* extract endianness if needed */ |
|
325 if (spec->width > 8) { |
|
326 if (!gst_structure_get_int (structure, "endianness", &endianness)) |
|
327 goto parse_error; |
|
328 } else { |
|
329 endianness = G_BYTE_ORDER; |
|
330 } |
|
331 |
|
332 spec->bigend = endianness == G_LITTLE_ENDIAN ? FALSE : TRUE; |
|
333 |
|
334 def = build_linear_format (spec->depth, spec->width, spec->sign ? 0 : 1, |
|
335 spec->bigend ? 1 : 0); |
|
336 |
|
337 if (def == NULL) |
|
338 goto parse_error; |
|
339 |
|
340 spec->format = def->format; |
|
341 |
|
342 bytes = spec->width >> 3; |
|
343 |
|
344 for (i = 0; i < spec->channels; i++) { |
|
345 for (j = 0; j < bytes; j++) { |
|
346 spec->silence_sample[i * bytes + j] = def->silence[j]; |
|
347 } |
|
348 } |
|
349 } else if (!strncmp (mimetype, "audio/x-raw-float", 17)) { |
|
350 |
|
351 spec->type = GST_BUFTYPE_FLOAT; |
|
352 |
|
353 /* extract the needed information from the cap */ |
|
354 if (!(gst_structure_get_int (structure, "rate", &spec->rate) && |
|
355 gst_structure_get_int (structure, "channels", &spec->channels) && |
|
356 gst_structure_get_int (structure, "width", &spec->width))) |
|
357 goto parse_error; |
|
358 |
|
359 /* match layout to format wrt to endianness */ |
|
360 switch (spec->width) { |
|
361 case 32: |
|
362 spec->format = |
|
363 G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT32_LE : GST_FLOAT32_BE; |
|
364 break; |
|
365 case 64: |
|
366 spec->format = |
|
367 G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT64_LE : GST_FLOAT64_BE; |
|
368 break; |
|
369 default: |
|
370 goto parse_error; |
|
371 } |
|
372 /* float silence is all zeros.. */ |
|
373 memset (spec->silence_sample, 0, 32); |
|
374 } else if (!strncmp (mimetype, "audio/x-alaw", 12)) { |
|
375 /* extract the needed information from the cap */ |
|
376 if (!(gst_structure_get_int (structure, "rate", &spec->rate) && |
|
377 gst_structure_get_int (structure, "channels", &spec->channels))) |
|
378 goto parse_error; |
|
379 |
|
380 spec->type = GST_BUFTYPE_A_LAW; |
|
381 spec->format = GST_A_LAW; |
|
382 spec->width = 8; |
|
383 spec->depth = 8; |
|
384 for (i = 0; i < spec->channels; i++) |
|
385 spec->silence_sample[i] = 0xd5; |
|
386 } else if (!strncmp (mimetype, "audio/x-mulaw", 13)) { |
|
387 /* extract the needed information from the cap */ |
|
388 if (!(gst_structure_get_int (structure, "rate", &spec->rate) && |
|
389 gst_structure_get_int (structure, "channels", &spec->channels))) |
|
390 goto parse_error; |
|
391 |
|
392 spec->type = GST_BUFTYPE_MU_LAW; |
|
393 spec->format = GST_MU_LAW; |
|
394 spec->width = 8; |
|
395 spec->depth = 8; |
|
396 for (i = 0; i < spec->channels; i++) |
|
397 spec->silence_sample[i] = 0xff; |
|
398 } else if (!strncmp (mimetype, "audio/x-iec958", 14)) { |
|
399 /* extract the needed information from the cap */ |
|
400 if (!(gst_structure_get_int (structure, "rate", &spec->rate))) |
|
401 goto parse_error; |
|
402 |
|
403 spec->type = GST_BUFTYPE_IEC958; |
|
404 spec->format = GST_IEC958; |
|
405 spec->width = 16; |
|
406 spec->depth = 16; |
|
407 spec->channels = 2; |
|
408 } else if (!strncmp (mimetype, "audio/x-ac3", 11)) { |
|
409 /* extract the needed information from the cap */ |
|
410 if (!(gst_structure_get_int (structure, "rate", &spec->rate))) |
|
411 goto parse_error; |
|
412 |
|
413 spec->type = GST_BUFTYPE_AC3; |
|
414 spec->format = GST_AC3; |
|
415 spec->width = 16; |
|
416 spec->depth = 16; |
|
417 spec->channels = 2; |
|
418 } else { |
|
419 goto parse_error; |
|
420 } |
|
421 |
|
422 spec->bytes_per_sample = (spec->width >> 3) * spec->channels; |
|
423 |
|
424 gst_caps_replace (&spec->caps, caps); |
|
425 |
|
426 g_return_val_if_fail (spec->latency_time != 0, FALSE); |
|
427 |
|
428 /* calculate suggested segsize and segtotal. segsize should be one unit |
|
429 * of 'latency_time' samples, scaling for the fact that latency_time is |
|
430 * currently stored in microseconds (FIXME: in 0.11) */ |
|
431 spec->segsize = gst_util_uint64_scale (spec->rate * spec->bytes_per_sample, |
|
432 spec->latency_time, GST_SECOND / GST_USECOND); |
|
433 /* Round to an integer number of samples */ |
|
434 spec->segsize -= spec->segsize % spec->bytes_per_sample; |
|
435 |
|
436 spec->segtotal = spec->buffer_time / spec->latency_time; |
|
437 |
|
438 gst_ring_buffer_debug_spec_caps (spec); |
|
439 gst_ring_buffer_debug_spec_buff (spec); |
|
440 |
|
441 return TRUE; |
|
442 |
|
443 /* ERRORS */ |
|
444 parse_error: |
|
445 { |
|
446 GST_DEBUG ("could not parse caps"); |
|
447 return FALSE; |
|
448 } |
|
449 } |
|
450 |
|
451 /** |
|
452 * gst_ring_buffer_set_callback: |
|
453 * @buf: the #GstRingBuffer to set the callback on |
|
454 * @cb: the callback to set |
|
455 * @user_data: user data passed to the callback |
|
456 * |
|
457 * Sets the given callback function on the buffer. This function |
|
458 * will be called every time a segment has been written to a device. |
|
459 * |
|
460 * MT safe. |
|
461 */ |
|
462 #ifdef __SYMBIAN32__ |
|
463 EXPORT_C |
|
464 #endif |
|
465 |
|
466 void |
|
467 gst_ring_buffer_set_callback (GstRingBuffer * buf, GstRingBufferCallback cb, |
|
468 gpointer user_data) |
|
469 { |
|
470 g_return_if_fail (GST_IS_RING_BUFFER (buf)); |
|
471 |
|
472 GST_OBJECT_LOCK (buf); |
|
473 buf->callback = cb; |
|
474 buf->cb_data = user_data; |
|
475 GST_OBJECT_UNLOCK (buf); |
|
476 } |
|
477 |
|
478 |
|
479 /** |
|
480 * gst_ring_buffer_open_device: |
|
481 * @buf: the #GstRingBuffer |
|
482 * |
|
483 * Open the audio device associated with the ring buffer. Does not perform any |
|
484 * setup on the device. You must open the device before acquiring the ring |
|
485 * buffer. |
|
486 * |
|
487 * Returns: TRUE if the device could be opened, FALSE on error. |
|
488 * |
|
489 * MT safe. |
|
490 */ |
|
491 #ifdef __SYMBIAN32__ |
|
492 EXPORT_C |
|
493 #endif |
|
494 |
|
495 gboolean |
|
496 gst_ring_buffer_open_device (GstRingBuffer * buf) |
|
497 { |
|
498 gboolean res = TRUE; |
|
499 GstRingBufferClass *rclass; |
|
500 |
|
501 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); |
|
502 |
|
503 GST_DEBUG_OBJECT (buf, "opening device"); |
|
504 |
|
505 GST_OBJECT_LOCK (buf); |
|
506 if (G_UNLIKELY (buf->open)) |
|
507 goto was_opened; |
|
508 |
|
509 buf->open = TRUE; |
|
510 |
|
511 /* if this fails, something is wrong in this file */ |
|
512 g_assert (!buf->acquired); |
|
513 |
|
514 rclass = GST_RING_BUFFER_GET_CLASS (buf); |
|
515 if (G_LIKELY (rclass->open_device)) |
|
516 res = rclass->open_device (buf); |
|
517 |
|
518 if (G_UNLIKELY (!res)) |
|
519 goto open_failed; |
|
520 |
|
521 GST_DEBUG_OBJECT (buf, "opened device"); |
|
522 |
|
523 done: |
|
524 GST_OBJECT_UNLOCK (buf); |
|
525 |
|
526 return res; |
|
527 |
|
528 /* ERRORS */ |
|
529 was_opened: |
|
530 { |
|
531 GST_DEBUG_OBJECT (buf, "Device for ring buffer already open"); |
|
532 g_warning ("Device for ring buffer %p already open, fix your code", buf); |
|
533 res = TRUE; |
|
534 goto done; |
|
535 } |
|
536 open_failed: |
|
537 { |
|
538 buf->open = FALSE; |
|
539 GST_DEBUG_OBJECT (buf, "failed opening device"); |
|
540 goto done; |
|
541 } |
|
542 } |
|
543 |
|
544 /** |
|
545 * gst_ring_buffer_close_device: |
|
546 * @buf: the #GstRingBuffer |
|
547 * |
|
548 * Close the audio device associated with the ring buffer. The ring buffer |
|
549 * should already have been released via gst_ring_buffer_release(). |
|
550 * |
|
551 * Returns: TRUE if the device could be closed, FALSE on error. |
|
552 * |
|
553 * MT safe. |
|
554 */ |
|
555 #ifdef __SYMBIAN32__ |
|
556 EXPORT_C |
|
557 #endif |
|
558 |
|
559 gboolean |
|
560 gst_ring_buffer_close_device (GstRingBuffer * buf) |
|
561 { |
|
562 gboolean res = TRUE; |
|
563 GstRingBufferClass *rclass; |
|
564 |
|
565 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); |
|
566 |
|
567 GST_DEBUG_OBJECT (buf, "closing device"); |
|
568 |
|
569 GST_OBJECT_LOCK (buf); |
|
570 if (G_UNLIKELY (!buf->open)) |
|
571 goto was_closed; |
|
572 |
|
573 if (G_UNLIKELY (buf->acquired)) |
|
574 goto was_acquired; |
|
575 |
|
576 buf->open = FALSE; |
|
577 |
|
578 rclass = GST_RING_BUFFER_GET_CLASS (buf); |
|
579 if (G_LIKELY (rclass->close_device)) |
|
580 res = rclass->close_device (buf); |
|
581 |
|
582 if (G_UNLIKELY (!res)) |
|
583 goto close_error; |
|
584 |
|
585 GST_DEBUG_OBJECT (buf, "closed device"); |
|
586 |
|
587 done: |
|
588 GST_OBJECT_UNLOCK (buf); |
|
589 |
|
590 return res; |
|
591 |
|
592 /* ERRORS */ |
|
593 was_closed: |
|
594 { |
|
595 GST_DEBUG_OBJECT (buf, "Device for ring buffer already closed"); |
|
596 g_warning ("Device for ring buffer %p already closed, fix your code", buf); |
|
597 res = TRUE; |
|
598 goto done; |
|
599 } |
|
600 was_acquired: |
|
601 { |
|
602 GST_DEBUG_OBJECT (buf, "Resources for ring buffer still acquired"); |
|
603 g_critical ("Resources for ring buffer %p still acquired", buf); |
|
604 res = FALSE; |
|
605 goto done; |
|
606 } |
|
607 close_error: |
|
608 { |
|
609 buf->open = TRUE; |
|
610 GST_DEBUG_OBJECT (buf, "error closing device"); |
|
611 goto done; |
|
612 } |
|
613 } |
|
614 |
|
615 /** |
|
616 * gst_ring_buffer_device_is_open: |
|
617 * @buf: the #GstRingBuffer |
|
618 * |
|
619 * Checks the status of the device associated with the ring buffer. |
|
620 * |
|
621 * Returns: TRUE if the device was open, FALSE if it was closed. |
|
622 * |
|
623 * MT safe. |
|
624 */ |
|
625 #ifdef __SYMBIAN32__ |
|
626 EXPORT_C |
|
627 #endif |
|
628 |
|
629 gboolean |
|
630 gst_ring_buffer_device_is_open (GstRingBuffer * buf) |
|
631 { |
|
632 gboolean res = TRUE; |
|
633 |
|
634 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); |
|
635 |
|
636 GST_OBJECT_LOCK (buf); |
|
637 res = buf->open; |
|
638 GST_OBJECT_UNLOCK (buf); |
|
639 |
|
640 return res; |
|
641 } |
|
642 |
|
643 |
|
644 /** |
|
645 * gst_ring_buffer_acquire: |
|
646 * @buf: the #GstRingBuffer to acquire |
|
647 * @spec: the specs of the buffer |
|
648 * |
|
649 * Allocate the resources for the ringbuffer. This function fills |
|
650 * in the data pointer of the ring buffer with a valid #GstBuffer |
|
651 * to which samples can be written. |
|
652 * |
|
653 * Returns: TRUE if the device could be acquired, FALSE on error. |
|
654 * |
|
655 * MT safe. |
|
656 */ |
|
657 #ifdef __SYMBIAN32__ |
|
658 EXPORT_C |
|
659 #endif |
|
660 |
|
661 gboolean |
|
662 gst_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) |
|
663 { |
|
664 gboolean res = FALSE; |
|
665 GstRingBufferClass *rclass; |
|
666 gint i, j; |
|
667 gint segsize, bps; |
|
668 |
|
669 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); |
|
670 |
|
671 GST_DEBUG_OBJECT (buf, "acquiring device"); |
|
672 |
|
673 GST_OBJECT_LOCK (buf); |
|
674 if (G_UNLIKELY (!buf->open)) |
|
675 goto not_opened; |
|
676 |
|
677 if (G_UNLIKELY (buf->acquired)) |
|
678 goto was_acquired; |
|
679 |
|
680 buf->acquired = TRUE; |
|
681 |
|
682 rclass = GST_RING_BUFFER_GET_CLASS (buf); |
|
683 if (G_LIKELY (rclass->acquire)) |
|
684 res = rclass->acquire (buf, spec); |
|
685 |
|
686 if (G_UNLIKELY (!res)) |
|
687 goto acquire_failed; |
|
688 |
|
689 if (G_UNLIKELY ((bps = buf->spec.bytes_per_sample) == 0)) |
|
690 goto invalid_bps; |
|
691 |
|
692 segsize = buf->spec.segsize; |
|
693 |
|
694 buf->samples_per_seg = segsize / bps; |
|
695 |
|
696 /* create an empty segment */ |
|
697 g_free (buf->empty_seg); |
|
698 buf->empty_seg = g_malloc (segsize); |
|
699 |
|
700 /* FIXME, we only have 32 silence samples, which might not be enough to |
|
701 * represent silence in all channels */ |
|
702 bps = MIN (bps, 32); |
|
703 for (i = 0, j = 0; i < segsize; i++) { |
|
704 buf->empty_seg[i] = buf->spec.silence_sample[j]; |
|
705 j = (j + 1) % bps; |
|
706 } |
|
707 GST_DEBUG_OBJECT (buf, "acquired device"); |
|
708 |
|
709 done: |
|
710 GST_OBJECT_UNLOCK (buf); |
|
711 |
|
712 return res; |
|
713 |
|
714 /* ERRORS */ |
|
715 not_opened: |
|
716 { |
|
717 GST_DEBUG_OBJECT (buf, "device not opened"); |
|
718 g_critical ("Device for %p not opened", buf); |
|
719 res = FALSE; |
|
720 goto done; |
|
721 } |
|
722 was_acquired: |
|
723 { |
|
724 res = TRUE; |
|
725 GST_DEBUG_OBJECT (buf, "device was acquired"); |
|
726 goto done; |
|
727 } |
|
728 acquire_failed: |
|
729 { |
|
730 buf->acquired = FALSE; |
|
731 GST_DEBUG_OBJECT (buf, "failed to acquire device"); |
|
732 goto done; |
|
733 } |
|
734 invalid_bps: |
|
735 { |
|
736 g_warning |
|
737 ("invalid bytes_per_sample from acquire ringbuffer, fix the element"); |
|
738 buf->acquired = FALSE; |
|
739 res = FALSE; |
|
740 goto done; |
|
741 } |
|
742 } |
|
743 |
|
744 /** |
|
745 * gst_ring_buffer_release: |
|
746 * @buf: the #GstRingBuffer to release |
|
747 * |
|
748 * Free the resources of the ringbuffer. |
|
749 * |
|
750 * Returns: TRUE if the device could be released, FALSE on error. |
|
751 * |
|
752 * MT safe. |
|
753 */ |
|
754 #ifdef __SYMBIAN32__ |
|
755 EXPORT_C |
|
756 #endif |
|
757 |
|
758 gboolean |
|
759 gst_ring_buffer_release (GstRingBuffer * buf) |
|
760 { |
|
761 gboolean res = FALSE; |
|
762 GstRingBufferClass *rclass; |
|
763 |
|
764 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); |
|
765 |
|
766 GST_DEBUG_OBJECT (buf, "releasing device"); |
|
767 |
|
768 gst_ring_buffer_stop (buf); |
|
769 |
|
770 GST_OBJECT_LOCK (buf); |
|
771 if (G_UNLIKELY (!buf->acquired)) |
|
772 goto was_released; |
|
773 |
|
774 buf->acquired = FALSE; |
|
775 |
|
776 /* if this fails, something is wrong in this file */ |
|
777 g_assert (buf->open == TRUE); |
|
778 |
|
779 rclass = GST_RING_BUFFER_GET_CLASS (buf); |
|
780 if (G_LIKELY (rclass->release)) |
|
781 res = rclass->release (buf); |
|
782 |
|
783 /* signal any waiters */ |
|
784 GST_DEBUG_OBJECT (buf, "signal waiter"); |
|
785 GST_RING_BUFFER_SIGNAL (buf); |
|
786 |
|
787 if (G_UNLIKELY (!res)) |
|
788 goto release_failed; |
|
789 |
|
790 g_free (buf->empty_seg); |
|
791 buf->empty_seg = NULL; |
|
792 GST_DEBUG_OBJECT (buf, "released device"); |
|
793 |
|
794 done: |
|
795 GST_OBJECT_UNLOCK (buf); |
|
796 |
|
797 return res; |
|
798 |
|
799 /* ERRORS */ |
|
800 was_released: |
|
801 { |
|
802 res = TRUE; |
|
803 GST_DEBUG_OBJECT (buf, "device was released"); |
|
804 goto done; |
|
805 } |
|
806 release_failed: |
|
807 { |
|
808 buf->acquired = TRUE; |
|
809 GST_DEBUG_OBJECT (buf, "failed to release device"); |
|
810 goto done; |
|
811 } |
|
812 } |
|
813 |
|
814 /** |
|
815 * gst_ring_buffer_is_acquired: |
|
816 * @buf: the #GstRingBuffer to check |
|
817 * |
|
818 * Check if the ringbuffer is acquired and ready to use. |
|
819 * |
|
820 * Returns: TRUE if the ringbuffer is acquired, FALSE on error. |
|
821 * |
|
822 * MT safe. |
|
823 */ |
|
824 #ifdef __SYMBIAN32__ |
|
825 EXPORT_C |
|
826 #endif |
|
827 |
|
828 gboolean |
|
829 gst_ring_buffer_is_acquired (GstRingBuffer * buf) |
|
830 { |
|
831 gboolean res; |
|
832 |
|
833 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); |
|
834 |
|
835 GST_OBJECT_LOCK (buf); |
|
836 res = buf->acquired; |
|
837 GST_OBJECT_UNLOCK (buf); |
|
838 |
|
839 return res; |
|
840 } |
|
841 |
|
842 /** |
|
843 * gst_ring_buffer_set_flushing: |
|
844 * @buf: the #GstRingBuffer to flush |
|
845 * @flushing: the new mode |
|
846 * |
|
847 * Set the ringbuffer to flushing mode or normal mode. |
|
848 * |
|
849 * MT safe. |
|
850 */ |
|
851 #ifdef __SYMBIAN32__ |
|
852 EXPORT_C |
|
853 #endif |
|
854 |
|
855 void |
|
856 gst_ring_buffer_set_flushing (GstRingBuffer * buf, gboolean flushing) |
|
857 { |
|
858 g_return_if_fail (GST_IS_RING_BUFFER (buf)); |
|
859 |
|
860 GST_OBJECT_LOCK (buf); |
|
861 buf->abidata.ABI.flushing = flushing; |
|
862 |
|
863 gst_ring_buffer_clear_all (buf); |
|
864 if (flushing) { |
|
865 gst_ring_buffer_pause_unlocked (buf); |
|
866 } |
|
867 GST_OBJECT_UNLOCK (buf); |
|
868 } |
|
869 |
|
870 /** |
|
871 * gst_ring_buffer_start: |
|
872 * @buf: the #GstRingBuffer to start |
|
873 * |
|
874 * Start processing samples from the ringbuffer. |
|
875 * |
|
876 * Returns: TRUE if the device could be started, FALSE on error. |
|
877 * |
|
878 * MT safe. |
|
879 */ |
|
880 #ifdef __SYMBIAN32__ |
|
881 EXPORT_C |
|
882 #endif |
|
883 |
|
884 gboolean |
|
885 gst_ring_buffer_start (GstRingBuffer * buf) |
|
886 { |
|
887 gboolean res = FALSE; |
|
888 GstRingBufferClass *rclass; |
|
889 gboolean resume = FALSE; |
|
890 |
|
891 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); |
|
892 |
|
893 GST_DEBUG_OBJECT (buf, "starting ringbuffer"); |
|
894 |
|
895 GST_OBJECT_LOCK (buf); |
|
896 if (G_UNLIKELY (buf->abidata.ABI.flushing)) |
|
897 goto flushing; |
|
898 |
|
899 if (G_UNLIKELY (!buf->acquired)) |
|
900 goto not_acquired; |
|
901 |
|
902 /* if stopped, set to started */ |
|
903 res = g_atomic_int_compare_and_exchange (&buf->state, |
|
904 GST_RING_BUFFER_STATE_STOPPED, GST_RING_BUFFER_STATE_STARTED); |
|
905 |
|
906 if (!res) { |
|
907 /* was not stopped, try from paused */ |
|
908 res = g_atomic_int_compare_and_exchange (&buf->state, |
|
909 GST_RING_BUFFER_STATE_PAUSED, GST_RING_BUFFER_STATE_STARTED); |
|
910 if (!res) { |
|
911 /* was not paused either, must be started then */ |
|
912 res = TRUE; |
|
913 GST_DEBUG_OBJECT (buf, "was started"); |
|
914 goto done; |
|
915 } |
|
916 resume = TRUE; |
|
917 GST_DEBUG_OBJECT (buf, "resuming"); |
|
918 } |
|
919 |
|
920 rclass = GST_RING_BUFFER_GET_CLASS (buf); |
|
921 if (resume) { |
|
922 if (G_LIKELY (rclass->resume)) |
|
923 res = rclass->resume (buf); |
|
924 } else { |
|
925 if (G_LIKELY (rclass->start)) |
|
926 res = rclass->start (buf); |
|
927 } |
|
928 |
|
929 if (G_UNLIKELY (!res)) { |
|
930 buf->state = GST_RING_BUFFER_STATE_PAUSED; |
|
931 GST_DEBUG_OBJECT (buf, "failed to start"); |
|
932 } else { |
|
933 GST_DEBUG_OBJECT (buf, "started"); |
|
934 } |
|
935 |
|
936 done: |
|
937 GST_OBJECT_UNLOCK (buf); |
|
938 |
|
939 return res; |
|
940 |
|
941 flushing: |
|
942 { |
|
943 GST_DEBUG_OBJECT (buf, "we are flushing"); |
|
944 GST_OBJECT_UNLOCK (buf); |
|
945 return FALSE; |
|
946 } |
|
947 not_acquired: |
|
948 { |
|
949 GST_DEBUG_OBJECT (buf, "we are not acquired"); |
|
950 GST_OBJECT_UNLOCK (buf); |
|
951 return FALSE; |
|
952 } |
|
953 } |
|
954 |
|
955 static gboolean |
|
956 gst_ring_buffer_pause_unlocked (GstRingBuffer * buf) |
|
957 { |
|
958 gboolean res = FALSE; |
|
959 GstRingBufferClass *rclass; |
|
960 |
|
961 GST_DEBUG_OBJECT (buf, "pausing ringbuffer"); |
|
962 |
|
963 /* if started, set to paused */ |
|
964 res = g_atomic_int_compare_and_exchange (&buf->state, |
|
965 GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_PAUSED); |
|
966 |
|
967 if (!res) |
|
968 goto not_started; |
|
969 |
|
970 /* signal any waiters */ |
|
971 GST_DEBUG_OBJECT (buf, "signal waiter"); |
|
972 GST_RING_BUFFER_SIGNAL (buf); |
|
973 |
|
974 rclass = GST_RING_BUFFER_GET_CLASS (buf); |
|
975 if (G_LIKELY (rclass->pause)) |
|
976 res = rclass->pause (buf); |
|
977 |
|
978 if (G_UNLIKELY (!res)) { |
|
979 buf->state = GST_RING_BUFFER_STATE_STARTED; |
|
980 GST_DEBUG_OBJECT (buf, "failed to pause"); |
|
981 } else { |
|
982 GST_DEBUG_OBJECT (buf, "paused"); |
|
983 } |
|
984 |
|
985 return res; |
|
986 |
|
987 not_started: |
|
988 { |
|
989 /* was not started */ |
|
990 GST_DEBUG_OBJECT (buf, "was not started"); |
|
991 return TRUE; |
|
992 } |
|
993 } |
|
994 |
|
995 /** |
|
996 * gst_ring_buffer_pause: |
|
997 * @buf: the #GstRingBuffer to pause |
|
998 * |
|
999 * Pause processing samples from the ringbuffer. |
|
1000 * |
|
1001 * Returns: TRUE if the device could be paused, FALSE on error. |
|
1002 * |
|
1003 * MT safe. |
|
1004 */ |
|
1005 #ifdef __SYMBIAN32__ |
|
1006 EXPORT_C |
|
1007 #endif |
|
1008 |
|
1009 gboolean |
|
1010 gst_ring_buffer_pause (GstRingBuffer * buf) |
|
1011 { |
|
1012 gboolean res = FALSE; |
|
1013 |
|
1014 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); |
|
1015 |
|
1016 GST_OBJECT_LOCK (buf); |
|
1017 if (G_UNLIKELY (buf->abidata.ABI.flushing)) |
|
1018 goto flushing; |
|
1019 |
|
1020 if (G_UNLIKELY (!buf->acquired)) |
|
1021 goto not_acquired; |
|
1022 |
|
1023 res = gst_ring_buffer_pause_unlocked (buf); |
|
1024 GST_OBJECT_UNLOCK (buf); |
|
1025 |
|
1026 return res; |
|
1027 |
|
1028 /* ERRORS */ |
|
1029 flushing: |
|
1030 { |
|
1031 GST_DEBUG_OBJECT (buf, "we are flushing"); |
|
1032 GST_OBJECT_UNLOCK (buf); |
|
1033 return FALSE; |
|
1034 } |
|
1035 not_acquired: |
|
1036 { |
|
1037 GST_DEBUG_OBJECT (buf, "not acquired"); |
|
1038 GST_OBJECT_UNLOCK (buf); |
|
1039 return FALSE; |
|
1040 } |
|
1041 } |
|
1042 |
|
1043 /** |
|
1044 * gst_ring_buffer_stop: |
|
1045 * @buf: the #GstRingBuffer to stop |
|
1046 * |
|
1047 * Stop processing samples from the ringbuffer. |
|
1048 * |
|
1049 * Returns: TRUE if the device could be stopped, FALSE on error. |
|
1050 * |
|
1051 * MT safe. |
|
1052 */ |
|
1053 #ifdef __SYMBIAN32__ |
|
1054 EXPORT_C |
|
1055 #endif |
|
1056 |
|
1057 gboolean |
|
1058 gst_ring_buffer_stop (GstRingBuffer * buf) |
|
1059 { |
|
1060 gboolean res = FALSE; |
|
1061 GstRingBufferClass *rclass; |
|
1062 |
|
1063 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); |
|
1064 |
|
1065 GST_DEBUG_OBJECT (buf, "stopping"); |
|
1066 |
|
1067 GST_OBJECT_LOCK (buf); |
|
1068 |
|
1069 /* if started, set to stopped */ |
|
1070 res = g_atomic_int_compare_and_exchange (&buf->state, |
|
1071 GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_STOPPED); |
|
1072 |
|
1073 if (!res) { |
|
1074 /* was not started, must be stopped then */ |
|
1075 GST_DEBUG_OBJECT (buf, "was not started"); |
|
1076 res = TRUE; |
|
1077 goto done; |
|
1078 } |
|
1079 |
|
1080 /* signal any waiters */ |
|
1081 GST_DEBUG_OBJECT (buf, "signal waiter"); |
|
1082 GST_RING_BUFFER_SIGNAL (buf); |
|
1083 |
|
1084 rclass = GST_RING_BUFFER_GET_CLASS (buf); |
|
1085 if (G_LIKELY (rclass->stop)) |
|
1086 res = rclass->stop (buf); |
|
1087 |
|
1088 if (G_UNLIKELY (!res)) { |
|
1089 buf->state = GST_RING_BUFFER_STATE_STARTED; |
|
1090 GST_DEBUG_OBJECT (buf, "failed to stop"); |
|
1091 } else { |
|
1092 GST_DEBUG_OBJECT (buf, "stopped"); |
|
1093 } |
|
1094 done: |
|
1095 GST_OBJECT_UNLOCK (buf); |
|
1096 |
|
1097 return res; |
|
1098 } |
|
1099 |
|
1100 /** |
|
1101 * gst_ring_buffer_delay: |
|
1102 * @buf: the #GstRingBuffer to query |
|
1103 * |
|
1104 * Get the number of samples queued in the audio device. This is |
|
1105 * usually less than the segment size but can be bigger when the |
|
1106 * implementation uses another internal buffer between the audio |
|
1107 * device. |
|
1108 * |
|
1109 * For playback ringbuffers this is the amount of samples transfered from the |
|
1110 * ringbuffer to the device but still not played. |
|
1111 * |
|
1112 * For capture ringbuffers this is the amount of samples in the device that are |
|
1113 * not yet transfered to the ringbuffer. |
|
1114 * |
|
1115 * Returns: The number of samples queued in the audio device. |
|
1116 * |
|
1117 * MT safe. |
|
1118 */ |
|
1119 #ifdef __SYMBIAN32__ |
|
1120 EXPORT_C |
|
1121 #endif |
|
1122 |
|
1123 guint |
|
1124 gst_ring_buffer_delay (GstRingBuffer * buf) |
|
1125 { |
|
1126 GstRingBufferClass *rclass; |
|
1127 guint res; |
|
1128 |
|
1129 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), 0); |
|
1130 |
|
1131 /* buffer must be acquired */ |
|
1132 if (G_UNLIKELY (!gst_ring_buffer_is_acquired (buf))) |
|
1133 goto not_acquired; |
|
1134 |
|
1135 rclass = GST_RING_BUFFER_GET_CLASS (buf); |
|
1136 if (G_LIKELY (rclass->delay)) |
|
1137 res = rclass->delay (buf); |
|
1138 else |
|
1139 res = 0; |
|
1140 |
|
1141 return res; |
|
1142 |
|
1143 not_acquired: |
|
1144 { |
|
1145 GST_DEBUG_OBJECT (buf, "not acquired"); |
|
1146 return 0; |
|
1147 } |
|
1148 } |
|
1149 |
|
1150 /** |
|
1151 * gst_ring_buffer_samples_done: |
|
1152 * @buf: the #GstRingBuffer to query |
|
1153 * |
|
1154 * Get the number of samples that were processed by the ringbuffer |
|
1155 * since it was last started. This does not include the number of samples not |
|
1156 * yet processed (see gst_ring_buffer_delay()). |
|
1157 * |
|
1158 * Returns: The number of samples processed by the ringbuffer. |
|
1159 * |
|
1160 * MT safe. |
|
1161 */ |
|
1162 #ifdef __SYMBIAN32__ |
|
1163 EXPORT_C |
|
1164 #endif |
|
1165 |
|
1166 guint64 |
|
1167 gst_ring_buffer_samples_done (GstRingBuffer * buf) |
|
1168 { |
|
1169 gint segdone; |
|
1170 guint64 samples; |
|
1171 |
|
1172 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), 0); |
|
1173 |
|
1174 /* get the amount of segments we processed */ |
|
1175 segdone = g_atomic_int_get (&buf->segdone); |
|
1176 |
|
1177 /* convert to samples */ |
|
1178 samples = ((guint64) segdone) * buf->samples_per_seg; |
|
1179 |
|
1180 return samples; |
|
1181 } |
|
1182 |
|
1183 /** |
|
1184 * gst_ring_buffer_set_sample: |
|
1185 * @buf: the #GstRingBuffer to use |
|
1186 * @sample: the sample number to set |
|
1187 * |
|
1188 * Make sure that the next sample written to the device is |
|
1189 * accounted for as being the @sample sample written to the |
|
1190 * device. This value will be used in reporting the current |
|
1191 * sample position of the ringbuffer. |
|
1192 * |
|
1193 * This function will also clear the buffer with silence. |
|
1194 * |
|
1195 * MT safe. |
|
1196 */ |
|
1197 #ifdef __SYMBIAN32__ |
|
1198 EXPORT_C |
|
1199 #endif |
|
1200 |
|
1201 void |
|
1202 gst_ring_buffer_set_sample (GstRingBuffer * buf, guint64 sample) |
|
1203 { |
|
1204 g_return_if_fail (GST_IS_RING_BUFFER (buf)); |
|
1205 |
|
1206 if (sample == -1) |
|
1207 sample = 0; |
|
1208 |
|
1209 if (G_UNLIKELY (buf->samples_per_seg == 0)) |
|
1210 return; |
|
1211 |
|
1212 /* FIXME, we assume the ringbuffer can restart at a random |
|
1213 * position, round down to the beginning and keep track of |
|
1214 * offset when calculating the processed samples. */ |
|
1215 buf->segbase = buf->segdone - sample / buf->samples_per_seg; |
|
1216 |
|
1217 gst_ring_buffer_clear_all (buf); |
|
1218 |
|
1219 GST_DEBUG_OBJECT (buf, "set sample to %llu, segbase %d", sample, |
|
1220 buf->segbase); |
|
1221 } |
|
1222 |
|
1223 /** |
|
1224 * gst_ring_buffer_clear_all: |
|
1225 * @buf: the #GstRingBuffer to clear |
|
1226 * |
|
1227 * Fill the ringbuffer with silence. |
|
1228 * |
|
1229 * MT safe. |
|
1230 */ |
|
1231 #ifdef __SYMBIAN32__ |
|
1232 EXPORT_C |
|
1233 #endif |
|
1234 |
|
1235 void |
|
1236 gst_ring_buffer_clear_all (GstRingBuffer * buf) |
|
1237 { |
|
1238 gint i; |
|
1239 |
|
1240 g_return_if_fail (GST_IS_RING_BUFFER (buf)); |
|
1241 |
|
1242 /* not fatal, we just are not negotiated yet */ |
|
1243 if (G_UNLIKELY (buf->spec.segtotal <= 0)) |
|
1244 return; |
|
1245 |
|
1246 GST_DEBUG_OBJECT (buf, "clear all segments"); |
|
1247 |
|
1248 for (i = 0; i < buf->spec.segtotal; i++) { |
|
1249 gst_ring_buffer_clear (buf, i); |
|
1250 } |
|
1251 } |
|
1252 |
|
1253 |
|
1254 static gboolean |
|
1255 wait_segment (GstRingBuffer * buf) |
|
1256 { |
|
1257 /* buffer must be started now or we deadlock since nobody is reading */ |
|
1258 if (G_UNLIKELY (g_atomic_int_get (&buf->state) != |
|
1259 GST_RING_BUFFER_STATE_STARTED)) { |
|
1260 /* see if we are allowed to start it */ |
|
1261 if (G_UNLIKELY (g_atomic_int_get (&buf->abidata.ABI.may_start) == FALSE)) |
|
1262 goto no_start; |
|
1263 |
|
1264 GST_DEBUG_OBJECT (buf, "start!"); |
|
1265 gst_ring_buffer_start (buf); |
|
1266 } |
|
1267 |
|
1268 /* take lock first, then update our waiting flag */ |
|
1269 GST_OBJECT_LOCK (buf); |
|
1270 if (G_UNLIKELY (buf->abidata.ABI.flushing)) |
|
1271 goto flushing; |
|
1272 |
|
1273 if (G_UNLIKELY (g_atomic_int_get (&buf->state) != |
|
1274 GST_RING_BUFFER_STATE_STARTED)) |
|
1275 goto not_started; |
|
1276 |
|
1277 if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) { |
|
1278 GST_DEBUG_OBJECT (buf, "waiting.."); |
|
1279 GST_RING_BUFFER_WAIT (buf); |
|
1280 |
|
1281 if (G_UNLIKELY (buf->abidata.ABI.flushing)) |
|
1282 goto flushing; |
|
1283 |
|
1284 if (G_UNLIKELY (g_atomic_int_get (&buf->state) != |
|
1285 GST_RING_BUFFER_STATE_STARTED)) |
|
1286 goto not_started; |
|
1287 } |
|
1288 GST_OBJECT_UNLOCK (buf); |
|
1289 |
|
1290 return TRUE; |
|
1291 |
|
1292 /* ERROR */ |
|
1293 not_started: |
|
1294 { |
|
1295 g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0); |
|
1296 GST_DEBUG_OBJECT (buf, "stopped processing"); |
|
1297 GST_OBJECT_UNLOCK (buf); |
|
1298 return FALSE; |
|
1299 } |
|
1300 flushing: |
|
1301 { |
|
1302 g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0); |
|
1303 GST_DEBUG_OBJECT (buf, "flushing"); |
|
1304 GST_OBJECT_UNLOCK (buf); |
|
1305 return FALSE; |
|
1306 } |
|
1307 no_start: |
|
1308 { |
|
1309 GST_DEBUG_OBJECT (buf, "not allowed to start"); |
|
1310 return FALSE; |
|
1311 } |
|
1312 } |
|
1313 |
|
1314 #define FWD_SAMPLES(s,se,d,de) \ |
|
1315 G_STMT_START { \ |
|
1316 /* no rate conversion */ \ |
|
1317 guint towrite = MIN (se + bps - s, de - d); \ |
|
1318 /* simple copy */ \ |
|
1319 if (!skip) \ |
|
1320 memcpy (d, s, towrite); \ |
|
1321 in_samples -= towrite / bps; \ |
|
1322 out_samples -= towrite / bps; \ |
|
1323 s += towrite; \ |
|
1324 GST_DEBUG ("copy %u bytes", towrite); \ |
|
1325 } G_STMT_END |
|
1326 |
|
1327 /* in_samples >= out_samples, rate > 1.0 */ |
|
1328 #define FWD_UP_SAMPLES(s,se,d,de) \ |
|
1329 G_STMT_START { \ |
|
1330 guint8 *sb = s, *db = d; \ |
|
1331 while (s <= se && d < de) { \ |
|
1332 if (!skip) \ |
|
1333 memcpy (d, s, bps); \ |
|
1334 s += bps; \ |
|
1335 *accum += outr; \ |
|
1336 if ((*accum << 1) >= inr) { \ |
|
1337 *accum -= inr; \ |
|
1338 d += bps; \ |
|
1339 } \ |
|
1340 } \ |
|
1341 in_samples -= (s - sb)/bps; \ |
|
1342 out_samples -= (d - db)/bps; \ |
|
1343 GST_DEBUG ("fwd_up end %d/%d",*accum,*toprocess); \ |
|
1344 } G_STMT_END |
|
1345 |
|
1346 /* out_samples > in_samples, for rates smaller than 1.0 */ |
|
1347 #define FWD_DOWN_SAMPLES(s,se,d,de) \ |
|
1348 G_STMT_START { \ |
|
1349 guint8 *sb = s, *db = d; \ |
|
1350 while (s <= se && d < de) { \ |
|
1351 if (!skip) \ |
|
1352 memcpy (d, s, bps); \ |
|
1353 d += bps; \ |
|
1354 *accum += inr; \ |
|
1355 if ((*accum << 1) >= outr) { \ |
|
1356 *accum -= outr; \ |
|
1357 s += bps; \ |
|
1358 } \ |
|
1359 } \ |
|
1360 in_samples -= (s - sb)/bps; \ |
|
1361 out_samples -= (d - db)/bps; \ |
|
1362 GST_DEBUG ("fwd_down end %d/%d",*accum,*toprocess); \ |
|
1363 } G_STMT_END |
|
1364 |
|
1365 #define REV_UP_SAMPLES(s,se,d,de) \ |
|
1366 G_STMT_START { \ |
|
1367 guint8 *sb = se, *db = d; \ |
|
1368 while (s <= se && d < de) { \ |
|
1369 if (!skip) \ |
|
1370 memcpy (d, se, bps); \ |
|
1371 se -= bps; \ |
|
1372 *accum += outr; \ |
|
1373 while ((*accum << 1) >= inr) { \ |
|
1374 *accum -= inr; \ |
|
1375 d += bps; \ |
|
1376 } \ |
|
1377 } \ |
|
1378 in_samples -= (sb - se)/bps; \ |
|
1379 out_samples -= (d - db)/bps; \ |
|
1380 GST_DEBUG ("rev_up end %d/%d",*accum,*toprocess); \ |
|
1381 } G_STMT_END |
|
1382 |
|
1383 #define REV_DOWN_SAMPLES(s,se,d,de) \ |
|
1384 G_STMT_START { \ |
|
1385 guint8 *sb = se, *db = d; \ |
|
1386 while (s <= se && d < de) { \ |
|
1387 if (!skip) \ |
|
1388 memcpy (d, se, bps); \ |
|
1389 d += bps; \ |
|
1390 *accum += inr; \ |
|
1391 while ((*accum << 1) >= outr) { \ |
|
1392 *accum -= outr; \ |
|
1393 se -= bps; \ |
|
1394 } \ |
|
1395 } \ |
|
1396 in_samples -= (sb - se)/bps; \ |
|
1397 out_samples -= (d - db)/bps; \ |
|
1398 GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess); \ |
|
1399 } G_STMT_END |
|
1400 |
|
1401 /** |
|
1402 * gst_ring_buffer_commit_full: |
|
1403 * @buf: the #GstRingBuffer to commit |
|
1404 * @sample: the sample position of the data |
|
1405 * @data: the data to commit |
|
1406 * @in_samples: the number of samples in the data to commit |
|
1407 * @out_samples: the number of samples to write to the ringbuffer |
|
1408 * @accum: accumulator for rate conversion. |
|
1409 * |
|
1410 * Commit @in_samples samples pointed to by @data to the ringbuffer @buf. |
|
1411 * |
|
1412 * @in_samples and @out_samples define the rate conversion to perform on the the |
|
1413 * samples in @data. For negative rates, @out_samples must be negative and |
|
1414 * @in_samples positive. |
|
1415 * |
|
1416 * When @out_samples is positive, the first sample will be written at position @sample |
|
1417 * in the ringbuffer. When @out_samples is negative, the last sample will be written to |
|
1418 * @sample in reverse order. |
|
1419 * |
|
1420 * @out_samples does not need to be a multiple of the segment size of the ringbuffer |
|
1421 * although it is recommended for optimal performance. |
|
1422 * |
|
1423 * @accum will hold a temporary accumulator used in rate conversion and should be |
|
1424 * set to 0 when this function is first called. In case the commit operation is |
|
1425 * interrupted, one can resume the processing by passing the previously returned |
|
1426 * @accum value back to this function. |
|
1427 * |
|
1428 * Returns: The number of samples written to the ringbuffer or -1 on error. The |
|
1429 * number of samples written can be less than @out_samples when @buf was interrupted |
|
1430 * with a flush or stop. |
|
1431 * |
|
1432 * Since: 0.10.11. |
|
1433 * |
|
1434 * MT safe. |
|
1435 */ |
|
1436 #ifdef __SYMBIAN32__ |
|
1437 EXPORT_C |
|
1438 #endif |
|
1439 |
|
1440 guint |
|
1441 gst_ring_buffer_commit_full (GstRingBuffer * buf, guint64 * sample, |
|
1442 guchar * data, gint in_samples, gint out_samples, gint * accum) |
|
1443 { |
|
1444 gint segdone; |
|
1445 gint segsize, segtotal, bps, sps; |
|
1446 guint8 *dest, *data_end; |
|
1447 gint writeseg, sampleoff; |
|
1448 gint *toprocess; |
|
1449 gint inr, outr; |
|
1450 gboolean reverse; |
|
1451 |
|
1452 if (G_UNLIKELY (in_samples == 0 || out_samples == 0)) |
|
1453 return in_samples; |
|
1454 |
|
1455 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1); |
|
1456 g_return_val_if_fail (buf->data != NULL, -1); |
|
1457 g_return_val_if_fail (data != NULL, -1); |
|
1458 |
|
1459 dest = GST_BUFFER_DATA (buf->data); |
|
1460 segsize = buf->spec.segsize; |
|
1461 segtotal = buf->spec.segtotal; |
|
1462 bps = buf->spec.bytes_per_sample; |
|
1463 sps = buf->samples_per_seg; |
|
1464 |
|
1465 reverse = out_samples < 0; |
|
1466 out_samples = ABS (out_samples); |
|
1467 |
|
1468 if (in_samples >= out_samples) |
|
1469 toprocess = &in_samples; |
|
1470 else |
|
1471 toprocess = &out_samples; |
|
1472 |
|
1473 inr = in_samples - 1; |
|
1474 outr = out_samples - 1; |
|
1475 |
|
1476 /* data_end points to the last sample we have to write, not past it. This is |
|
1477 * needed to properly handle reverse playback: it points to the last sample. */ |
|
1478 data_end = data + (bps * inr); |
|
1479 |
|
1480 /* figure out the segment and the offset inside the segment where |
|
1481 * the first sample should be written. */ |
|
1482 writeseg = *sample / sps; |
|
1483 sampleoff = (*sample % sps) * bps; |
|
1484 |
|
1485 /* write out all samples */ |
|
1486 while (*toprocess > 0) { |
|
1487 gint avail; |
|
1488 guint8 *d, *d_end; |
|
1489 gint ws; |
|
1490 gboolean skip; |
|
1491 |
|
1492 while (TRUE) { |
|
1493 gint diff; |
|
1494 |
|
1495 /* get the currently processed segment */ |
|
1496 segdone = g_atomic_int_get (&buf->segdone) - buf->segbase; |
|
1497 |
|
1498 /* see how far away it is from the write segment */ |
|
1499 diff = writeseg - segdone; |
|
1500 |
|
1501 GST_DEBUG |
|
1502 ("pointer at %d, write to %d-%d, diff %d, segtotal %d, segsize %d", |
|
1503 segdone, writeseg, sampleoff, diff, segtotal, segsize); |
|
1504 |
|
1505 /* segment too far ahead, writer too slow, we need to drop, hopefully UNLIKELY */ |
|
1506 if (G_UNLIKELY (diff < 0)) { |
|
1507 /* we need to drop one segment at a time, pretend we wrote a |
|
1508 * segment. */ |
|
1509 skip = TRUE; |
|
1510 break; |
|
1511 } |
|
1512 |
|
1513 /* write segment is within writable range, we can break the loop and |
|
1514 * start writing the data. */ |
|
1515 if (diff < segtotal) { |
|
1516 skip = FALSE; |
|
1517 break; |
|
1518 } |
|
1519 |
|
1520 /* else we need to wait for the segment to become writable. */ |
|
1521 if (!wait_segment (buf)) |
|
1522 goto not_started; |
|
1523 } |
|
1524 |
|
1525 /* we can write now */ |
|
1526 ws = writeseg % segtotal; |
|
1527 avail = MIN (segsize - sampleoff, bps * out_samples); |
|
1528 |
|
1529 d = dest + (ws * segsize) + sampleoff; |
|
1530 d_end = d + avail; |
|
1531 *sample += avail / bps; |
|
1532 |
|
1533 GST_DEBUG_OBJECT (buf, "write @%p seg %d, sps %d, off %d, avail %d", |
|
1534 dest + ws * segsize, ws, sps, sampleoff, avail); |
|
1535 |
|
1536 if (G_LIKELY (inr == outr && !reverse)) { |
|
1537 /* no rate conversion, simply copy samples */ |
|
1538 FWD_SAMPLES (data, data_end, d, d_end); |
|
1539 } else if (!reverse) { |
|
1540 if (inr >= outr) |
|
1541 /* forward speed up */ |
|
1542 FWD_UP_SAMPLES (data, data_end, d, d_end); |
|
1543 else |
|
1544 /* forward slow down */ |
|
1545 FWD_DOWN_SAMPLES (data, data_end, d, d_end); |
|
1546 } else { |
|
1547 if (inr >= outr) |
|
1548 /* reverse speed up */ |
|
1549 REV_UP_SAMPLES (data, data_end, d, d_end); |
|
1550 else |
|
1551 /* reverse slow down */ |
|
1552 REV_DOWN_SAMPLES (data, data_end, d, d_end); |
|
1553 } |
|
1554 |
|
1555 /* for the next iteration we write to the next segment at the beginning. */ |
|
1556 writeseg++; |
|
1557 sampleoff = 0; |
|
1558 } |
|
1559 /* we consumed all samples here */ |
|
1560 data = data_end + bps; |
|
1561 |
|
1562 done: |
|
1563 return inr - ((data_end - data) / bps); |
|
1564 |
|
1565 /* ERRORS */ |
|
1566 not_started: |
|
1567 { |
|
1568 GST_DEBUG_OBJECT (buf, "stopped processing"); |
|
1569 goto done; |
|
1570 } |
|
1571 } |
|
1572 |
|
1573 /** |
|
1574 * gst_ring_buffer_commit: |
|
1575 * @buf: the #GstRingBuffer to commit |
|
1576 * @sample: the sample position of the data |
|
1577 * @data: the data to commit |
|
1578 * @len: the number of samples in the data to commit |
|
1579 * |
|
1580 * Same as gst_ring_buffer_commit_full() but with a in_samples and out_samples |
|
1581 * equal to @len, ignoring accum. |
|
1582 * |
|
1583 * Returns: The number of samples written to the ringbuffer or -1 on |
|
1584 * error. |
|
1585 * |
|
1586 * MT safe. |
|
1587 */ |
|
1588 #ifdef __SYMBIAN32__ |
|
1589 EXPORT_C |
|
1590 #endif |
|
1591 |
|
1592 guint |
|
1593 gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data, |
|
1594 guint len) |
|
1595 { |
|
1596 guint res; |
|
1597 guint64 samplep = sample; |
|
1598 |
|
1599 res = gst_ring_buffer_commit_full (buf, &samplep, data, len, len, NULL); |
|
1600 |
|
1601 return res; |
|
1602 } |
|
1603 |
|
1604 /** |
|
1605 * gst_ring_buffer_read: |
|
1606 * @buf: the #GstRingBuffer to read from |
|
1607 * @sample: the sample position of the data |
|
1608 * @data: where the data should be read |
|
1609 * @len: the number of samples in data to read |
|
1610 * |
|
1611 * Read @len samples from the ringbuffer into the memory pointed |
|
1612 * to by @data. |
|
1613 * The first sample should be read from position @sample in |
|
1614 * the ringbuffer. |
|
1615 * |
|
1616 * @len should not be a multiple of the segment size of the ringbuffer |
|
1617 * although it is recommended. |
|
1618 * |
|
1619 * Returns: The number of samples read from the ringbuffer or -1 on |
|
1620 * error. |
|
1621 * |
|
1622 * MT safe. |
|
1623 */ |
|
1624 #ifdef __SYMBIAN32__ |
|
1625 EXPORT_C |
|
1626 #endif |
|
1627 |
|
1628 guint |
|
1629 gst_ring_buffer_read (GstRingBuffer * buf, guint64 sample, guchar * data, |
|
1630 guint len) |
|
1631 { |
|
1632 gint segdone; |
|
1633 gint segsize, segtotal, bps, sps; |
|
1634 guint8 *dest; |
|
1635 guint to_read; |
|
1636 |
|
1637 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1); |
|
1638 g_return_val_if_fail (buf->data != NULL, -1); |
|
1639 g_return_val_if_fail (data != NULL, -1); |
|
1640 |
|
1641 dest = GST_BUFFER_DATA (buf->data); |
|
1642 segsize = buf->spec.segsize; |
|
1643 segtotal = buf->spec.segtotal; |
|
1644 bps = buf->spec.bytes_per_sample; |
|
1645 sps = buf->samples_per_seg; |
|
1646 |
|
1647 to_read = len; |
|
1648 /* read enough samples */ |
|
1649 while (to_read > 0) { |
|
1650 gint sampleslen; |
|
1651 gint readseg, sampleoff; |
|
1652 |
|
1653 /* figure out the segment and the offset inside the segment where |
|
1654 * the sample should be read from. */ |
|
1655 readseg = sample / sps; |
|
1656 sampleoff = (sample % sps); |
|
1657 |
|
1658 while (TRUE) { |
|
1659 gint diff; |
|
1660 |
|
1661 /* get the currently processed segment */ |
|
1662 segdone = g_atomic_int_get (&buf->segdone) - buf->segbase; |
|
1663 |
|
1664 /* see how far away it is from the read segment, normally segdone (where |
|
1665 * the hardware is writing) is bigger than readseg (where software is |
|
1666 * reading) */ |
|
1667 diff = segdone - readseg; |
|
1668 |
|
1669 GST_DEBUG |
|
1670 ("pointer at %d, sample %llu, read from %d-%d, to_read %d, diff %d, segtotal %d, segsize %d", |
|
1671 segdone, sample, readseg, sampleoff, to_read, diff, segtotal, |
|
1672 segsize); |
|
1673 |
|
1674 /* segment too far ahead, reader too slow */ |
|
1675 if (G_UNLIKELY (diff >= segtotal)) { |
|
1676 /* pretend we read an empty segment. */ |
|
1677 sampleslen = MIN (sps, to_read); |
|
1678 memcpy (data, buf->empty_seg, sampleslen * bps); |
|
1679 goto next; |
|
1680 } |
|
1681 |
|
1682 /* read segment is within readable range, we can break the loop and |
|
1683 * start reading the data. */ |
|
1684 if (diff > 0) |
|
1685 break; |
|
1686 |
|
1687 /* else we need to wait for the segment to become readable. */ |
|
1688 if (!wait_segment (buf)) |
|
1689 goto not_started; |
|
1690 } |
|
1691 |
|
1692 /* we can read now */ |
|
1693 readseg = readseg % segtotal; |
|
1694 sampleslen = MIN (sps - sampleoff, to_read); |
|
1695 |
|
1696 GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, sampleslen %d", |
|
1697 dest + readseg * segsize, readseg, sampleoff, sampleslen); |
|
1698 |
|
1699 memcpy (data, dest + (readseg * segsize) + (sampleoff * bps), |
|
1700 (sampleslen * bps)); |
|
1701 |
|
1702 next: |
|
1703 to_read -= sampleslen; |
|
1704 sample += sampleslen; |
|
1705 data += sampleslen * bps; |
|
1706 } |
|
1707 |
|
1708 return len - to_read; |
|
1709 |
|
1710 /* ERRORS */ |
|
1711 not_started: |
|
1712 { |
|
1713 GST_DEBUG_OBJECT (buf, "stopped processing"); |
|
1714 return len - to_read; |
|
1715 } |
|
1716 } |
|
1717 |
|
1718 /** |
|
1719 * gst_ring_buffer_prepare_read: |
|
1720 * @buf: the #GstRingBuffer to read from |
|
1721 * @segment: the segment to read |
|
1722 * @readptr: the pointer to the memory where samples can be read |
|
1723 * @len: the number of bytes to read |
|
1724 * |
|
1725 * Returns a pointer to memory where the data from segment @segment |
|
1726 * can be found. This function is mostly used by subclasses. |
|
1727 * |
|
1728 * Returns: FALSE if the buffer is not started. |
|
1729 * |
|
1730 * MT safe. |
|
1731 */ |
|
1732 #ifdef __SYMBIAN32__ |
|
1733 EXPORT_C |
|
1734 #endif |
|
1735 |
|
1736 gboolean |
|
1737 gst_ring_buffer_prepare_read (GstRingBuffer * buf, gint * segment, |
|
1738 guint8 ** readptr, gint * len) |
|
1739 { |
|
1740 guint8 *data; |
|
1741 gint segdone; |
|
1742 |
|
1743 g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); |
|
1744 |
|
1745 /* buffer must be started */ |
|
1746 if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED) |
|
1747 return FALSE; |
|
1748 |
|
1749 g_return_val_if_fail (buf->data != NULL, FALSE); |
|
1750 g_return_val_if_fail (segment != NULL, FALSE); |
|
1751 g_return_val_if_fail (readptr != NULL, FALSE); |
|
1752 g_return_val_if_fail (len != NULL, FALSE); |
|
1753 |
|
1754 data = GST_BUFFER_DATA (buf->data); |
|
1755 |
|
1756 /* get the position of the pointer */ |
|
1757 segdone = g_atomic_int_get (&buf->segdone); |
|
1758 |
|
1759 *segment = segdone % buf->spec.segtotal; |
|
1760 *len = buf->spec.segsize; |
|
1761 *readptr = data + *segment * *len; |
|
1762 |
|
1763 /* callback to fill the memory with data, for pull based |
|
1764 * scheduling. */ |
|
1765 if (buf->callback) |
|
1766 buf->callback (buf, *readptr, *len, buf->cb_data); |
|
1767 |
|
1768 GST_LOG ("prepare read from segment %d (real %d) @%p", |
|
1769 *segment, segdone, *readptr); |
|
1770 |
|
1771 return TRUE; |
|
1772 } |
|
1773 |
|
1774 /** |
|
1775 * gst_ring_buffer_advance: |
|
1776 * @buf: the #GstRingBuffer to advance |
|
1777 * @advance: the number of segments written |
|
1778 * |
|
1779 * Subclasses should call this function to notify the fact that |
|
1780 * @advance segments are now processed by the device. |
|
1781 * |
|
1782 * MT safe. |
|
1783 */ |
|
1784 #ifdef __SYMBIAN32__ |
|
1785 EXPORT_C |
|
1786 #endif |
|
1787 |
|
1788 void |
|
1789 gst_ring_buffer_advance (GstRingBuffer * buf, guint advance) |
|
1790 { |
|
1791 g_return_if_fail (GST_IS_RING_BUFFER (buf)); |
|
1792 |
|
1793 /* update counter */ |
|
1794 g_atomic_int_add (&buf->segdone, advance); |
|
1795 |
|
1796 /* the lock is already taken when the waiting flag is set, |
|
1797 * we grab the lock as well to make sure the waiter is actually |
|
1798 * waiting for the signal */ |
|
1799 if (g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0)) { |
|
1800 GST_OBJECT_LOCK (buf); |
|
1801 GST_DEBUG_OBJECT (buf, "signal waiter"); |
|
1802 GST_RING_BUFFER_SIGNAL (buf); |
|
1803 GST_OBJECT_UNLOCK (buf); |
|
1804 } |
|
1805 } |
|
1806 |
|
1807 /** |
|
1808 * gst_ring_buffer_clear: |
|
1809 * @buf: the #GstRingBuffer to clear |
|
1810 * @segment: the segment to clear |
|
1811 * |
|
1812 * Clear the given segment of the buffer with silence samples. |
|
1813 * This function is used by subclasses. |
|
1814 * |
|
1815 * MT safe. |
|
1816 */ |
|
1817 #ifdef __SYMBIAN32__ |
|
1818 EXPORT_C |
|
1819 #endif |
|
1820 |
|
1821 void |
|
1822 gst_ring_buffer_clear (GstRingBuffer * buf, gint segment) |
|
1823 { |
|
1824 guint8 *data; |
|
1825 |
|
1826 g_return_if_fail (GST_IS_RING_BUFFER (buf)); |
|
1827 |
|
1828 /* no data means it's already cleared */ |
|
1829 if (G_UNLIKELY (buf->data == NULL)) |
|
1830 return; |
|
1831 |
|
1832 /* no empty_seg means it's not opened */ |
|
1833 if (G_UNLIKELY (buf->empty_seg == NULL)) |
|
1834 return; |
|
1835 |
|
1836 segment %= buf->spec.segtotal; |
|
1837 |
|
1838 data = GST_BUFFER_DATA (buf->data); |
|
1839 data += segment * buf->spec.segsize; |
|
1840 |
|
1841 GST_LOG ("clear segment %d @%p", segment, data); |
|
1842 |
|
1843 memcpy (data, buf->empty_seg, buf->spec.segsize); |
|
1844 } |
|
1845 |
|
1846 /** |
|
1847 * gst_ring_buffer_may_start: |
|
1848 * @buf: the #GstRingBuffer |
|
1849 * @allowed: the new value |
|
1850 * |
|
1851 * Tell the ringbuffer that it is allowed to start playback when |
|
1852 * the ringbuffer is filled with samples. |
|
1853 * |
|
1854 * Since: 0.10.6 |
|
1855 * |
|
1856 * MT safe. |
|
1857 */ |
|
1858 #ifdef __SYMBIAN32__ |
|
1859 EXPORT_C |
|
1860 #endif |
|
1861 |
|
1862 void |
|
1863 gst_ring_buffer_may_start (GstRingBuffer * buf, gboolean allowed) |
|
1864 { |
|
1865 g_return_if_fail (GST_IS_RING_BUFFER (buf)); |
|
1866 |
|
1867 GST_LOG_OBJECT (buf, "may start: %d", allowed); |
|
1868 gst_atomic_int_set (&buf->abidata.ABI.may_start, allowed); |
|
1869 } |