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);
47 guint sz;
49 GST_LOG_OBJECT (pool->element, "creating buffer %p in pool %p", self, pool);
51 self->pool = (GstDucatiBufferPool *)
52 gst_mini_object_ref (GST_MINI_OBJECT (pool));
54 GST_BUFFER_DATA (self) =
55 gst_ducati_alloc_2d (pool->padded_width, pool->padded_height, &sz);
56 GST_BUFFER_SIZE (self) = sz;
58 gst_buffer_set_caps (GST_BUFFER (self), pool->caps);
60 return self;
61 }
63 static void
64 gst_ducati_buffer_finalize (GstDucatiBuffer * self)
65 {
66 GstDucatiBufferPool *pool = self->pool;
67 gboolean resuscitated = FALSE;
69 GST_LOG_OBJECT (pool->element, "finalizing buffer %p", self);
71 GST_DUCATI_BUFFERPOOL_LOCK (pool);
72 if (pool->running) {
73 resuscitated = TRUE;
75 GST_LOG_OBJECT (pool->element, "reviving buffer %p", self);
76 gst_buffer_ref (GST_BUFFER (self));
78 /* insert self into freelist */
79 self->next = pool->freelist;
80 pool->freelist = self;
81 } else {
82 GST_LOG_OBJECT (pool->element, "the pool is shutting down");
83 }
84 GST_DUCATI_BUFFERPOOL_UNLOCK (pool);
86 if (!resuscitated) {
87 GST_LOG_OBJECT (pool->element,
88 "buffer %p (data %p, len %u) not recovered, freeing",
89 self, GST_BUFFER_DATA (self), GST_BUFFER_SIZE (self));
90 MemMgr_Free ((void *) GST_BUFFER_DATA (self));
91 GST_BUFFER_DATA (self) = NULL;
92 gst_mini_object_unref (GST_MINI_OBJECT (pool));
93 GST_MINI_OBJECT_CLASS (buffer_parent_class)->
94 finalize (GST_MINI_OBJECT (self));
95 }
96 }
98 static void
99 gst_ducati_buffer_class_init (gpointer g_class, gpointer class_data)
100 {
101 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
103 buffer_parent_class = g_type_class_peek_parent (g_class);
105 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
106 GST_DEBUG_FUNCPTR (gst_ducati_buffer_finalize);
107 }
109 GType
110 gst_ducati_buffer_get_type (void)
111 {
112 static GType type;
114 if (G_UNLIKELY (type == 0)) {
115 static const GTypeInfo info = {
116 .class_size = sizeof (GstBufferClass),
117 .class_init = gst_ducati_buffer_class_init,
118 .instance_size = sizeof (GstDucatiBuffer),
119 };
120 type = g_type_register_static (GST_TYPE_BUFFER,
121 "GstDucatiBuffer", &info, 0);
122 }
123 return type;
124 }
126 /*
127 * GstDucatiBufferPool
128 */
130 static GstMiniObjectClass *bufferpool_parent_class = NULL;
132 /** create new bufferpool */
133 GstDucatiBufferPool *
134 gst_ducati_bufferpool_new (GstElement * element, GstCaps * caps)
135 {
136 GstDucatiBufferPool *self = (GstDucatiBufferPool *)
137 gst_mini_object_new (GST_TYPE_DUCATIBUFFERPOOL);
138 GstStructure *s = gst_caps_get_structure (caps, 0);
140 self->element = gst_object_ref (element);
141 gst_structure_get_int (s, "width", &self->padded_width);
142 gst_structure_get_int (s, "height", &self->padded_height);
143 self->caps = gst_caps_ref (caps);
144 self->freelist = NULL;
145 self->lock = g_mutex_new ();
146 self->running = TRUE;
148 return self;
149 }
151 /** destroy existing bufferpool */
152 void
153 gst_ducati_bufferpool_destroy (GstDucatiBufferPool * self)
154 {
155 g_return_if_fail (self);
157 GST_DUCATI_BUFFERPOOL_LOCK (self);
158 self->running = FALSE;
159 GST_DUCATI_BUFFERPOOL_UNLOCK (self);
161 GST_DEBUG_OBJECT (self->element, "destroy pool");
163 /* free all buffers on the freelist */
164 while (self->freelist) {
165 GstDucatiBuffer *buf = self->freelist;
166 self->freelist = buf->next;
167 gst_buffer_unref (GST_BUFFER (buf));
168 }
170 gst_mini_object_unref (GST_MINI_OBJECT (self));
171 }
173 /** get buffer from bufferpool, allocate new buffer if needed */
174 GstDucatiBuffer *
175 gst_ducati_bufferpool_get (GstDucatiBufferPool * self, GstBuffer * orig)
176 {
177 GstDucatiBuffer *buf = NULL;
179 g_return_if_fail (self);
181 GST_DUCATI_BUFFERPOOL_LOCK (self);
182 if (self->running) {
183 /* re-use a buffer off the freelist if any are available
184 */
185 if (self->freelist) {
186 buf = self->freelist;
187 self->freelist = buf->next;
188 } else {
189 buf = gst_ducati_buffer_new (self);
190 }
191 buf->orig = orig;
192 }
193 GST_DUCATI_BUFFERPOOL_UNLOCK (self);
195 if (buf && orig) {
196 GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_TIMESTAMP (orig);
197 GST_BUFFER_DURATION (buf) = GST_BUFFER_DURATION (orig);
198 }
200 return buf;
201 }
203 static void
204 gst_ducati_bufferpool_finalize (GstDucatiBufferPool * self)
205 {
206 g_mutex_free (self->lock);
207 gst_caps_unref (self->caps);
208 gst_object_unref (self->element);
209 GST_MINI_OBJECT_CLASS (bufferpool_parent_class)->
210 finalize (GST_MINI_OBJECT (self));
211 }
213 static void
214 gst_ducati_bufferpool_class_init (gpointer g_class, gpointer class_data)
215 {
216 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
218 bufferpool_parent_class = g_type_class_peek_parent (g_class);
220 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
221 GST_DEBUG_FUNCPTR (gst_ducati_bufferpool_finalize);
222 }
224 GType
225 gst_ducati_bufferpool_get_type (void)
226 {
227 static GType type;
229 if (G_UNLIKELY (type == 0)) {
230 static const GTypeInfo info = {
231 .class_size = sizeof (GstMiniObjectClass),
232 .class_init = gst_ducati_bufferpool_class_init,
233 .instance_size = sizeof (GstDucatiBufferPool),
234 };
235 type = g_type_register_static (GST_TYPE_MINI_OBJECT,
236 "GstDucatiBufferPool", &info, 0);
237 }
238 return type;
239 }