f72e6056f5717ffa4ab7958aad9de83fe4519834
[platform/upstream/gstreamer.git] / gst / audioresample / buffer.c
1
2 #ifndef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5
6 #include <audioresample/buffer.h>
7 #include <glib.h>
8 #include <string.h>
9 #include <audioresample/debug.h>
10
11 static void audioresample_buffer_free_mem (AudioresampleBuffer * buffer,
12     void *);
13 static void audioresample_buffer_free_subbuffer (AudioresampleBuffer * buffer,
14     void *priv);
15
16
17 AudioresampleBuffer *
18 audioresample_buffer_new (void)
19 {
20   AudioresampleBuffer *buffer;
21
22   buffer = g_new0 (AudioresampleBuffer, 1);
23   buffer->ref_count = 1;
24   return buffer;
25 }
26
27 AudioresampleBuffer *
28 audioresample_buffer_new_and_alloc (int size)
29 {
30   AudioresampleBuffer *buffer = audioresample_buffer_new ();
31
32   buffer->data = g_malloc (size);
33   buffer->length = size;
34   buffer->free = audioresample_buffer_free_mem;
35
36   return buffer;
37 }
38
39 AudioresampleBuffer *
40 audioresample_buffer_new_with_data (void *data, int size)
41 {
42   AudioresampleBuffer *buffer = audioresample_buffer_new ();
43
44   buffer->data = data;
45   buffer->length = size;
46   buffer->free = audioresample_buffer_free_mem;
47
48   return buffer;
49 }
50
51 AudioresampleBuffer *
52 audioresample_buffer_new_subbuffer (AudioresampleBuffer * buffer, int offset,
53     int length)
54 {
55   AudioresampleBuffer *subbuffer = audioresample_buffer_new ();
56
57   if (buffer->parent) {
58     audioresample_buffer_ref (buffer->parent);
59     subbuffer->parent = buffer->parent;
60   } else {
61     audioresample_buffer_ref (buffer);
62     subbuffer->parent = buffer;
63   }
64   subbuffer->data = buffer->data + offset;
65   subbuffer->length = length;
66   subbuffer->free = audioresample_buffer_free_subbuffer;
67
68   return subbuffer;
69 }
70
71 void
72 audioresample_buffer_ref (AudioresampleBuffer * buffer)
73 {
74   buffer->ref_count++;
75 }
76
77 void
78 audioresample_buffer_unref (AudioresampleBuffer * buffer)
79 {
80   buffer->ref_count--;
81   if (buffer->ref_count == 0) {
82     if (buffer->free)
83       buffer->free (buffer, buffer->priv);
84     g_free (buffer);
85   }
86 }
87
88 static void
89 audioresample_buffer_free_mem (AudioresampleBuffer * buffer, void *priv)
90 {
91   g_free (buffer->data);
92 }
93
94 static void
95 audioresample_buffer_free_subbuffer (AudioresampleBuffer * buffer, void *priv)
96 {
97   audioresample_buffer_unref (buffer->parent);
98 }
99
100
101 AudioresampleBufferQueue *
102 audioresample_buffer_queue_new (void)
103 {
104   return g_new0 (AudioresampleBufferQueue, 1);
105 }
106
107 int
108 audioresample_buffer_queue_get_depth (AudioresampleBufferQueue * queue)
109 {
110   return queue->depth;
111 }
112
113 int
114 audioresample_buffer_queue_get_offset (AudioresampleBufferQueue * queue)
115 {
116   return queue->offset;
117 }
118
119 void
120 audioresample_buffer_queue_free (AudioresampleBufferQueue * queue)
121 {
122   GList *g;
123
124   for (g = g_list_first (queue->buffers); g; g = g_list_next (g)) {
125     audioresample_buffer_unref ((AudioresampleBuffer *) g->data);
126   }
127   g_list_free (queue->buffers);
128   g_free (queue);
129 }
130
131 void
132 audioresample_buffer_queue_push (AudioresampleBufferQueue * queue,
133     AudioresampleBuffer * buffer)
134 {
135   queue->buffers = g_list_append (queue->buffers, buffer);
136   queue->depth += buffer->length;
137 }
138
139 AudioresampleBuffer *
140 audioresample_buffer_queue_pull (AudioresampleBufferQueue * queue, int length)
141 {
142   GList *g;
143   AudioresampleBuffer *newbuffer;
144   AudioresampleBuffer *buffer;
145   AudioresampleBuffer *subbuffer;
146
147   g_return_val_if_fail (length > 0, NULL);
148
149   if (queue->depth < length) {
150     return NULL;
151   }
152
153   RESAMPLE_LOG ("pulling %d, %d available", length, queue->depth);
154
155   g = g_list_first (queue->buffers);
156   buffer = g->data;
157
158   if (buffer->length > length) {
159     newbuffer = audioresample_buffer_new_subbuffer (buffer, 0, length);
160
161     subbuffer = audioresample_buffer_new_subbuffer (buffer, length,
162         buffer->length - length);
163     g->data = subbuffer;
164     audioresample_buffer_unref (buffer);
165   } else {
166     int offset = 0;
167
168     newbuffer = audioresample_buffer_new_and_alloc (length);
169
170     while (offset < length) {
171       g = g_list_first (queue->buffers);
172       buffer = g->data;
173
174       if (buffer->length > length - offset) {
175         int n = length - offset;
176
177         memcpy (newbuffer->data + offset, buffer->data, n);
178         subbuffer =
179             audioresample_buffer_new_subbuffer (buffer, n, buffer->length - n);
180         g->data = subbuffer;
181         audioresample_buffer_unref (buffer);
182         offset += n;
183       } else {
184         memcpy (newbuffer->data + offset, buffer->data, buffer->length);
185
186         queue->buffers = g_list_delete_link (queue->buffers, g);
187         offset += buffer->length;
188         audioresample_buffer_unref (buffer);
189       }
190     }
191   }
192
193   queue->depth -= length;
194   queue->offset += length;
195
196   return newbuffer;
197 }
198
199 AudioresampleBuffer *
200 audioresample_buffer_queue_peek (AudioresampleBufferQueue * queue, int length)
201 {
202   GList *g;
203   AudioresampleBuffer *newbuffer;
204   AudioresampleBuffer *buffer;
205   int offset = 0;
206
207   g_return_val_if_fail (length > 0, NULL);
208
209   if (queue->depth < length) {
210     return NULL;
211   }
212
213   RESAMPLE_LOG ("peeking %d, %d available", length, queue->depth);
214
215   g = g_list_first (queue->buffers);
216   buffer = g->data;
217   if (buffer->length > length) {
218     newbuffer = audioresample_buffer_new_subbuffer (buffer, 0, length);
219   } else {
220     newbuffer = audioresample_buffer_new_and_alloc (length);
221     while (offset < length) {
222       buffer = g->data;
223
224       if (buffer->length > length - offset) {
225         int n = length - offset;
226
227         memcpy (newbuffer->data + offset, buffer->data, n);
228         offset += n;
229       } else {
230         memcpy (newbuffer->data + offset, buffer->data, buffer->length);
231         offset += buffer->length;
232       }
233       g = g_list_next (g);
234     }
235   }
236
237   return newbuffer;
238 }