Imported Upstream version 0.10.23
[profile/ivi/gst-plugins-bad.git] / ext / opencv / gstopencvvideofilter.c
1 /*
2  * GStreamer
3  * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
4  * 
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Alternatively, the contents of this file may be used under the
24  * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
25  * which case the following provisions apply instead of the ones
26  * mentioned above:
27  *
28  * This library is free software; you can redistribute it and/or
29  * modify it under the terms of the GNU Library General Public
30  * License as published by the Free Software Foundation; either
31  * version 2 of the License, or (at your option) any later version.
32  *
33  * This library is distributed in the hope that it will be useful,
34  * but WITHOUT ANY WARRANTY; without even the implied warranty of
35  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
36  * Library General Public License for more details.
37  *
38  * You should have received a copy of the GNU Library General Public
39  * License along with this library; if not, write to the
40  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
41  * Boston, MA 02111-1307, USA.
42  */
43
44 /* TODO opencv can do scaling for some cases */
45
46 #ifdef HAVE_CONFIG_H
47 #  include <config.h>
48 #endif
49
50 #include <gst/gst.h>
51
52 #include "gstopencvvideofilter.h"
53 #include "gstopencvutils.h"
54
55 GST_DEBUG_CATEGORY_STATIC (gst_opencv_video_filter_debug);
56 #define GST_CAT_DEFAULT gst_opencv_video_filter_debug
57
58 /* Filter signals and args */
59 enum
60 {
61   /* FILL ME */
62   LAST_SIGNAL
63 };
64
65 enum
66 {
67   PROP_0
68 };
69
70 static GstElementClass *parent_class = NULL;
71
72 static void gst_opencv_video_filter_class_init (GstOpencvVideoFilterClass *
73     klass);
74 static void gst_opencv_video_filter_init (GstOpencvVideoFilter * trans,
75     GstOpencvVideoFilterClass * klass);
76 static void gst_opencv_video_filter_base_init (gpointer gclass);
77
78 static gboolean gst_opencv_video_filter_set_caps (GstBaseTransform * trans,
79     GstCaps * incaps, GstCaps * outcaps);
80 static GstFlowReturn gst_opencv_video_filter_transform_ip (GstBaseTransform *
81     trans, GstBuffer * buf);
82 static GstFlowReturn gst_opencv_video_filter_transform (GstBaseTransform *
83     trans, GstBuffer * inbuf, GstBuffer * outbuf);
84
85 static void gst_opencv_video_filter_set_property (GObject * object,
86     guint prop_id, const GValue * value, GParamSpec * pspec);
87 static void gst_opencv_video_filter_get_property (GObject * object,
88     guint prop_id, GValue * value, GParamSpec * pspec);
89
90 GType
91 gst_opencv_video_filter_get_type (void)
92 {
93   static volatile gsize opencv_base_transform_type = 0;
94
95   if (g_once_init_enter (&opencv_base_transform_type)) {
96     GType _type;
97     static const GTypeInfo opencv_base_transform_info = {
98       sizeof (GstOpencvVideoFilterClass),
99       (GBaseInitFunc) gst_opencv_video_filter_base_init,
100       NULL,
101       (GClassInitFunc) gst_opencv_video_filter_class_init,
102       NULL,
103       NULL,
104       sizeof (GstOpencvVideoFilter),
105       0,
106       (GInstanceInitFunc) gst_opencv_video_filter_init,
107     };
108
109     _type = g_type_register_static (GST_TYPE_VIDEO_FILTER,
110         "GstOpencvVideoFilter", &opencv_base_transform_info,
111         G_TYPE_FLAG_ABSTRACT);
112     g_once_init_leave (&opencv_base_transform_type, _type);
113   }
114   return opencv_base_transform_type;
115 }
116
117 /* Clean up */
118 static void
119 gst_opencv_video_filter_finalize (GObject * obj)
120 {
121   GstOpencvVideoFilter *transform = GST_OPENCV_VIDEO_FILTER (obj);
122
123   if (transform->cvImage)
124     cvReleaseImage (&transform->cvImage);
125
126   G_OBJECT_CLASS (parent_class)->finalize (obj);
127 }
128
129 /* GObject vmethod implementations */
130 static void
131 gst_opencv_video_filter_base_init (gpointer gclass)
132 {
133 }
134
135 static void
136 gst_opencv_video_filter_class_init (GstOpencvVideoFilterClass * klass)
137 {
138   GObjectClass *gobject_class;
139   GstBaseTransformClass *basetrans_class;
140
141   gobject_class = (GObjectClass *) klass;
142   basetrans_class = (GstBaseTransformClass *) klass;
143   parent_class = g_type_class_peek_parent (klass);
144
145   GST_DEBUG_CATEGORY_INIT (gst_opencv_video_filter_debug,
146       "opencvbasetransform", 0, "opencvbasetransform element");
147
148   gobject_class->finalize =
149       GST_DEBUG_FUNCPTR (gst_opencv_video_filter_finalize);
150   gobject_class->set_property = gst_opencv_video_filter_set_property;
151   gobject_class->get_property = gst_opencv_video_filter_get_property;
152
153   basetrans_class->transform = gst_opencv_video_filter_transform;
154   basetrans_class->transform_ip = gst_opencv_video_filter_transform_ip;
155   basetrans_class->set_caps = gst_opencv_video_filter_set_caps;
156 }
157
158 static void
159 gst_opencv_video_filter_init (GstOpencvVideoFilter * transform,
160     GstOpencvVideoFilterClass * bclass)
161 {
162 }
163
164 static GstFlowReturn
165 gst_opencv_video_filter_transform (GstBaseTransform * trans,
166     GstBuffer * inbuf, GstBuffer * outbuf)
167 {
168   GstOpencvVideoFilter *transform;
169   GstOpencvVideoFilterClass *fclass;
170
171   transform = GST_OPENCV_VIDEO_FILTER (trans);
172   fclass = GST_OPENCV_VIDEO_FILTER_GET_CLASS (transform);
173
174   g_return_val_if_fail (fclass->cv_trans_func != NULL, GST_FLOW_ERROR);
175   g_return_val_if_fail (transform->cvImage != NULL, GST_FLOW_ERROR);
176   g_return_val_if_fail (transform->out_cvImage != NULL, GST_FLOW_ERROR);
177
178   transform->cvImage->imageData = (char *) GST_BUFFER_DATA (inbuf);
179   transform->out_cvImage->imageData = (char *) GST_BUFFER_DATA (outbuf);
180   return fclass->cv_trans_func (transform, inbuf, transform->cvImage, outbuf,
181       transform->out_cvImage);
182 }
183
184 static GstFlowReturn
185 gst_opencv_video_filter_transform_ip (GstBaseTransform * trans,
186     GstBuffer * buffer)
187 {
188   GstOpencvVideoFilter *transform;
189   GstOpencvVideoFilterClass *fclass;
190
191   transform = GST_OPENCV_VIDEO_FILTER (trans);
192   fclass = GST_OPENCV_VIDEO_FILTER_GET_CLASS (transform);
193
194   g_return_val_if_fail (fclass->cv_trans_ip_func != NULL, GST_FLOW_ERROR);
195   g_return_val_if_fail (transform->cvImage != NULL, GST_FLOW_ERROR);
196
197   /* TODO this is not always needed and should be solved at BaseTransform
198    * level */
199   buffer = gst_buffer_make_writable (buffer);
200
201   transform->cvImage->imageData = (char *) GST_BUFFER_DATA (buffer);
202
203   /* FIXME how to release buffer? */
204   return fclass->cv_trans_ip_func (transform, buffer, transform->cvImage);
205 }
206
207 static gboolean
208 gst_opencv_video_filter_set_caps (GstBaseTransform * trans, GstCaps * incaps,
209     GstCaps * outcaps)
210 {
211   GstOpencvVideoFilter *transform = GST_OPENCV_VIDEO_FILTER (trans);
212   GstOpencvVideoFilterClass *klass =
213       GST_OPENCV_VIDEO_FILTER_GET_CLASS (transform);
214   gint in_width, in_height;
215   gint in_depth, in_channels;
216   gint out_width, out_height;
217   gint out_depth, out_channels;
218   GError *in_err = NULL;
219   GError *out_err = NULL;
220
221   if (!gst_opencv_parse_iplimage_params_from_caps (incaps, &in_width,
222           &in_height, &in_depth, &in_channels, &in_err)) {
223     GST_WARNING_OBJECT (transform, "Failed to parse input caps: %s",
224         in_err->message);
225     g_error_free (in_err);
226     return FALSE;
227   }
228
229   if (!gst_opencv_parse_iplimage_params_from_caps (outcaps, &out_width,
230           &out_height, &out_depth, &out_channels, &out_err)) {
231     GST_WARNING_OBJECT (transform, "Failed to parse output caps: %s",
232         out_err->message);
233     g_error_free (out_err);
234     return FALSE;
235   }
236
237   if (klass->cv_set_caps) {
238     if (!klass->cv_set_caps (transform, in_width, in_height, in_depth,
239             in_channels, out_width, out_height, out_depth, out_channels))
240       return FALSE;
241   }
242
243   if (transform->cvImage) {
244     cvReleaseImage (&transform->cvImage);
245   }
246   if (transform->out_cvImage) {
247     cvReleaseImage (&transform->out_cvImage);
248   }
249
250   transform->cvImage =
251       cvCreateImageHeader (cvSize (in_width, in_height), in_depth, in_channels);
252   transform->out_cvImage =
253       cvCreateImageHeader (cvSize (out_width, out_height), out_depth,
254       out_channels);
255
256   gst_base_transform_set_in_place (GST_BASE_TRANSFORM (transform),
257       transform->in_place);
258   return TRUE;
259 }
260
261 static void
262 gst_opencv_video_filter_set_property (GObject * object, guint prop_id,
263     const GValue * value, GParamSpec * pspec)
264 {
265   switch (prop_id) {
266     default:
267       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
268       break;
269   }
270 }
271
272 static void
273 gst_opencv_video_filter_get_property (GObject * object, guint prop_id,
274     GValue * value, GParamSpec * pspec)
275 {
276   switch (prop_id) {
277     default:
278       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
279       break;
280   }
281 }
282
283 void
284 gst_opencv_video_filter_set_in_place (GstOpencvVideoFilter * transform,
285     gboolean ip)
286 {
287   transform->in_place = ip;
288   gst_base_transform_set_in_place (GST_BASE_TRANSFORM (transform), ip);
289 }