1 /*
2 * GStreamer
3 * Copyright (c) 2010, Texas Instruments Incorporated
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation
8 * version 2.1 of the License.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
20 #include "gstducatibufferpool.h"
22 /*
23 * GstDucatiBuffer
24 */
26 static GstBufferClass *buffer_parent_class;
28 /* Get the original buffer, or whatever is the best output buffer.
29 * Consumes the input reference, produces the output reference
30 */
31 GstBuffer *
32 gst_ducati_buffer_get (GstDucatiBuffer * self)
33 {
34 if (self->orig) {
35 // TODO copy to orig buffer.. if needed.
36 gst_buffer_unref (self->orig);
37 self->orig = NULL;
38 }
39 return GST_BUFFER (self);
40 }
42 static GstDucatiBuffer *
43 gst_ducati_buffer_new (GstDucatiBufferPool * pool)
44 {
45 GstDucatiBuffer *self = (GstDucatiBuffer *)
46 gst_mini_object_new (GST_TYPE_DUCATIBUFFER);
48 GST_LOG_OBJECT (pool->element, "creating buffer %p in pool %p", self, pool);
50 self->pool = (GstDucatiBufferPool *)
51 gst_mini_object_ref (GST_MINI_OBJECT (pool));
53 GST_BUFFER_DATA (self) = gst_ducati_alloc_1d (pool->size);
54 GST_BUFFER_SIZE (self) = pool->size;
56 gst_buffer_set_caps (GST_BUFFER (self), pool->caps);
58 return self;
59 }
61 static void
62 gst_ducati_buffer_finalize (GstDucatiBuffer * self)
63 {
64 GstDucatiBufferPool *pool = self->pool;
65 gboolean resuscitated = FALSE;
67 GST_LOG_OBJECT (pool->element, "finalizing buffer %p", self);
69 GST_DUCATI_BUFFERPOOL_LOCK (pool);
70 if (pool->running) {
71 resuscitated = TRUE;
73 GST_LOG_OBJECT (pool->element, "reviving buffer %p", self);
74 gst_buffer_ref (GST_BUFFER (self));
76 /* insert self into freelist */
77 self->next = pool->freelist;
78 pool->freelist = self;
79 } else {
80 GST_LOG_OBJECT (pool->element, "the pool is shutting down");
81 }
82 GST_DUCATI_BUFFERPOOL_UNLOCK (pool);
84 if (!resuscitated) {
85 GST_LOG_OBJECT (pool->element,
86 "buffer %p (data %p, len %u) not recovered, freeing",
87 self, GST_BUFFER_DATA (self), GST_BUFFER_SIZE (self));
88 MemMgr_Free ((void *) GST_BUFFER_DATA (self));
89 GST_BUFFER_DATA (self) = NULL;
90 gst_mini_object_unref (GST_MINI_OBJECT (pool));
91 GST_MINI_OBJECT_CLASS (buffer_parent_class)->
92 finalize (GST_MINI_OBJECT (self));
93 }
94 }
96 static void
97 gst_ducati_buffer_class_init (gpointer g_class, gpointer class_data)
98 {
99 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
101 buffer_parent_class = g_type_class_peek_parent (g_class);
103 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
104 GST_DEBUG_FUNCPTR (gst_ducati_buffer_finalize);
105 }
107 GType
108 gst_ducati_buffer_get_type (void)
109 {
110 static GType type;
112 if (G_UNLIKELY (type == 0)) {
113 static const GTypeInfo info = {
114 .class_size = sizeof (GstBufferClass),
115 .class_init = gst_ducati_buffer_class_init,
116 .instance_size = sizeof (GstDucatiBuffer),
117 };
118 type = g_type_register_static (GST_TYPE_BUFFER,
119 "GstDucatiBuffer", &info, 0);
120 }
121 return type;
122 }
124 /*
125 * GstDucatiBufferPool
126 */
128 static GstMiniObjectClass *bufferpool_parent_class = NULL;
130 /** create new bufferpool */
131 GstDucatiBufferPool *
132 gst_ducati_bufferpool_new (GstElement * element, GstCaps * caps, guint size)
133 {
134 GstDucatiBufferPool *self = (GstDucatiBufferPool *)
135 gst_mini_object_new (GST_TYPE_DUCATIBUFFERPOOL);
137 self->element = gst_object_ref (element);
138 if (caps) {
139 GstStructure *s = gst_caps_get_structure (caps, 0);
141 self->caps = gst_caps_ref (caps);
142 gst_structure_get_int (s, "width", &self->padded_width);
143 gst_structure_get_int (s, "height", &self->padded_height);
144 } else {
145 self->padded_width = 0;
146 self->padded_height = 0;
147 self->caps = NULL;
148 }
149 self->size = size;
150 self->freelist = NULL;
151 self->lock = g_mutex_new ();
152 self->running = TRUE;
154 return self;
155 }
157 /** destroy existing bufferpool */
158 void
159 gst_ducati_bufferpool_destroy (GstDucatiBufferPool * self)
160 {
161 g_return_if_fail (self);
163 GST_DUCATI_BUFFERPOOL_LOCK (self);
164 self->running = FALSE;
165 GST_DUCATI_BUFFERPOOL_UNLOCK (self);
167 GST_DEBUG_OBJECT (self->element, "destroy pool");
169 /* free all buffers on the freelist */
170 while (self->freelist) {
171 GstDucatiBuffer *buf = self->freelist;
172 self->freelist = buf->next;
173 gst_buffer_unref (GST_BUFFER (buf));
174 }
176 gst_mini_object_unref (GST_MINI_OBJECT (self));
177 }
179 /** get buffer from bufferpool, allocate new buffer if needed */
180 GstDucatiBuffer *
181 gst_ducati_bufferpool_get (GstDucatiBufferPool * self, GstBuffer * orig)
182 {
183 GstDucatiBuffer *buf = NULL;
185 g_return_val_if_fail (self, NULL);
187 GST_DUCATI_BUFFERPOOL_LOCK (self);
188 if (self->running) {
189 /* re-use a buffer off the freelist if any are available
190 */
191 if (self->freelist) {
192 buf = self->freelist;
193 self->freelist = buf->next;
194 } else {
195 buf = gst_ducati_buffer_new (self);
196 }
197 buf->orig = orig;
198 }
199 GST_DUCATI_BUFFERPOOL_UNLOCK (self);
201 if (buf && orig) {
202 GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_TIMESTAMP (orig);
203 GST_BUFFER_DURATION (buf) = GST_BUFFER_DURATION (orig);
204 }
206 return buf;
207 }
209 static void
210 gst_ducati_bufferpool_finalize (GstDucatiBufferPool * self)
211 {
212 g_mutex_free (self->lock);
213 if (self->caps)
214 gst_caps_unref (self->caps);
215 gst_object_unref (self->element);
216 GST_MINI_OBJECT_CLASS (bufferpool_parent_class)->
217 finalize (GST_MINI_OBJECT (self));
218 }
220 static void
221 gst_ducati_bufferpool_class_init (gpointer g_class, gpointer class_data)
222 {
223 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
225 bufferpool_parent_class = g_type_class_peek_parent (g_class);
227 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
228 GST_DEBUG_FUNCPTR (gst_ducati_bufferpool_finalize);
229 }
231 GType
232 gst_ducati_bufferpool_get_type (void)
233 {
234 static GType type;
236 if (G_UNLIKELY (type == 0)) {
237 static const GTypeInfo info = {
238 .class_size = sizeof (GstMiniObjectClass),
239 .class_init = gst_ducati_bufferpool_class_init,
240 .instance_size = sizeof (GstDucatiBufferPool),
241 };
242 type = g_type_register_static (GST_TYPE_MINI_OBJECT,
243 "GstDucatiBufferPool", &info, 0);
244 }
245 return type;
246 }