close #333784 unref the result of gst_pad_get_parent() by: Christophe Fergeau.
[platform/upstream/gstreamer.git] / ext / libmng / gstmngenc.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * Filter:
5  * Copyright (C) 2000 Donald A. Graft
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  * Library General Public License for more details.
11  *
12  * You should have received a copy of the GNU Library General Public
13  * License along with this library; if not, write to the
14  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15  * Boston, MA 02111-1307, USA.
16  *
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 #include <string.h>
23 #include <gst/gst.h>
24 #include "gstmngenc.h"
25 #include <gst/video/video.h>
26
27 #define MAX_HEIGHT              4096
28
29
30 GstElementDetails gst_mngenc_details = {
31   "MNG encoder",
32   "Codec/Encoder/Image",
33   "Encode a video frame to an .mng video",
34   "Wim Taymans <wim@fluendo.com>",
35 };
36
37
38 /* Filter signals and args */
39 enum
40 {
41   /* FILL ME */
42   LAST_SIGNAL
43 };
44
45 #define DEFAULT_SNAPSHOT        TRUE
46
47 enum
48 {
49   ARG_0,
50   ARG_SNAPSHOT,
51   ARG_NEWMEDIA
52 };
53
54 static void gst_mngenc_base_init (gpointer g_class);
55 static void gst_mngenc_class_init (GstMngEncClass * klass);
56 static void gst_mngenc_init (GstMngEnc * mngenc);
57 static void gst_mngenc_set_property (GObject * object,
58     guint prop_id, const GValue * value, GParamSpec * pspec);
59 static void gst_mngenc_get_property (GObject * object,
60     guint prop_id, GValue * value, GParamSpec * pspec);
61
62 static void gst_mngenc_chain (GstPad * pad, GstData * _data);
63
64 GstPadTemplate *mngenc_src_template, *mngenc_sink_template;
65
66 static GstElementClass *parent_class = NULL;
67
68
69 GType
70 gst_mngenc_get_type (void)
71 {
72   static GType mngenc_type = 0;
73
74   if (!mngenc_type) {
75     static const GTypeInfo mngenc_info = {
76       sizeof (GstMngEncClass),
77       gst_mngenc_base_init,
78       NULL,
79       (GClassInitFunc) gst_mngenc_class_init,
80       NULL,
81       NULL,
82       sizeof (GstMngEnc),
83       0,
84       (GInstanceInitFunc) gst_mngenc_init,
85     };
86
87     mngenc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstMngEnc",
88         &mngenc_info, 0);
89   }
90   return mngenc_type;
91 }
92
93 static GstCaps *
94 mng_caps_factory (void)
95 {
96   return gst_caps_new_simple ("video/x-mng",
97       "width", GST_TYPE_INT_RANGE, 16, 4096,
98       "height", GST_TYPE_INT_RANGE, 16, 4096,
99       "framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE, NULL);
100 }
101
102
103 static GstCaps *
104 raw_caps_factory (void)
105 {
106   return gst_caps_from_string (GST_VIDEO_CAPS_RGB);
107 }
108
109 static void
110 gst_mngenc_base_init (gpointer g_class)
111 {
112   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
113   GstCaps *raw_caps, *mng_caps;
114
115   raw_caps = raw_caps_factory ();
116   mng_caps = mng_caps_factory ();
117
118   mngenc_sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
119       GST_PAD_ALWAYS, raw_caps);
120
121   mngenc_src_template = gst_pad_template_new ("src", GST_PAD_SRC,
122       GST_PAD_ALWAYS, mng_caps);
123
124   gst_element_class_add_pad_template (element_class, mngenc_sink_template);
125   gst_element_class_add_pad_template (element_class, mngenc_src_template);
126   gst_element_class_set_details (element_class, &gst_mngenc_details);
127 }
128
129 static void
130 gst_mngenc_class_init (GstMngEncClass * klass)
131 {
132   GObjectClass *gobject_class;
133   GstElementClass *gstelement_class;
134
135   gobject_class = (GObjectClass *) klass;
136   gstelement_class = (GstElementClass *) klass;
137
138   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
139
140   g_object_class_install_property (gobject_class, ARG_SNAPSHOT,
141       g_param_spec_boolean ("snapshot", "Snapshot",
142           "Send EOS after encoding a frame, useful for snapshots",
143           DEFAULT_SNAPSHOT, (GParamFlags) G_PARAM_READWRITE));
144
145   g_object_class_install_property (gobject_class, ARG_NEWMEDIA,
146       g_param_spec_boolean ("newmedia", "newmedia",
147           "Send new media discontinuity after encoding each frame",
148           FALSE, (GParamFlags) G_PARAM_READWRITE));
149
150   gstelement_class->get_property = gst_mngenc_get_property;
151   gstelement_class->set_property = gst_mngenc_set_property;
152 }
153
154
155 static GstPadLinkReturn
156 gst_mngenc_sinklink (GstPad * pad, const GstCaps * caps)
157 {
158   GstMngEnc *mngenc;
159   gdouble fps;
160   GstStructure *structure;
161   GstPadLinkReturn result;
162
163   mngenc = GST_MNGENC (gst_pad_get_parent (pad));
164
165   structure = gst_caps_get_structure (caps, 0);
166   gst_structure_get_int (structure, "width", &mngenc->width);
167   gst_structure_get_int (structure, "height", &mngenc->height);
168   gst_structure_get_double (structure, "framerate", &fps);
169   gst_structure_get_int (structure, "bpp", &mngenc->bpp);
170
171   caps = gst_caps_new_simple ("video/x-mng",
172       "framerate", G_TYPE_DOUBLE, fps,
173       "width", G_TYPE_INT, mngenc->width,
174       "height", G_TYPE_INT, mngenc->height, NULL);
175
176   result = gst_pad_try_set_caps (mngenc->srcpad, caps);
177   gst_object_unref (mngenc);
178
179   return result;
180 }
181
182 static void
183 gst_mngenc_init (GstMngEnc * mngenc)
184 {
185   mngenc->sinkpad = gst_pad_new_from_template (mngenc_sink_template, "sink");
186   gst_element_add_pad (GST_ELEMENT (mngenc), mngenc->sinkpad);
187
188   mngenc->srcpad = gst_pad_new ("src", GST_PAD_SRC);
189   gst_element_add_pad (GST_ELEMENT (mngenc), mngenc->srcpad);
190
191   gst_pad_set_chain_function (mngenc->sinkpad, gst_mngenc_chain);
192   gst_pad_set_link_function (mngenc->sinkpad, gst_mngenc_sinklink);
193
194   mngenc->snapshot = DEFAULT_SNAPSHOT;
195   mngenc->newmedia = FALSE;
196 }
197
198 static void
199 gst_mngenc_chain (GstPad * pad, GstData * _data)
200 {
201   GstBuffer *buf = GST_BUFFER (_data);
202   GstMngEnc *mngenc;
203
204   mngenc = GST_MNGENC (gst_pad_get_parent (pad));
205
206   /* FIXME, do something here */
207
208   gst_buffer_unref (buf);
209   gst_object_unref (mngenc);
210 }
211
212
213 static void
214 gst_mngenc_get_property (GObject * object,
215     guint prop_id, GValue * value, GParamSpec * pspec)
216 {
217   GstMngEnc *mngenc;
218
219   mngenc = GST_MNGENC (object);
220
221   switch (prop_id) {
222     case ARG_SNAPSHOT:
223       g_value_set_boolean (value, mngenc->snapshot);
224       break;
225     case ARG_NEWMEDIA:
226       g_value_set_boolean (value, mngenc->newmedia);
227       break;
228     default:
229       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
230       break;
231   }
232 }
233
234
235 static void
236 gst_mngenc_set_property (GObject * object,
237     guint prop_id, const GValue * value, GParamSpec * pspec)
238 {
239   GstMngEnc *mngenc;
240
241   mngenc = GST_MNGENC (object);
242
243   switch (prop_id) {
244     case ARG_SNAPSHOT:
245       mngenc->snapshot = g_value_get_boolean (value);
246       break;
247     case ARG_NEWMEDIA:
248       mngenc->newmedia = g_value_get_boolean (value);
249       break;
250     default:
251       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
252       break;
253   }
254 }