2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
26 #include <gst/video/video.h>
27 #include "gsty4mencode.h"
29 static GstElementDetails y4mencode_details = GST_ELEMENT_DETAILS (
31 "Codec/Encoder/Video",
32 "Encodes a YUV frame into the yuv4mpeg format (mjpegtools)",
33 "Wim Taymans <wim.taymans@chello.be>"
37 /* Filter signals and args */
47 GST_PAD_TEMPLATE_FACTORY (y4mencode_src_factory,
53 "application/x-yuv4mpeg",
54 "y4mversion", GST_PROPS_INT (1)
58 GST_PAD_TEMPLATE_FACTORY (y4mencode_sink_factory,
65 GST_VIDEO_YUV_PAD_TEMPLATE_PROPS (
66 GST_PROPS_FOURCC (GST_STR_FOURCC ("I420")))
70 static void gst_y4mencode_base_init (gpointer g_class);
71 static void gst_y4mencode_class_init (GstY4mEncodeClass *klass);
72 static void gst_y4mencode_init (GstY4mEncode *filter);
74 static void gst_y4mencode_set_property (GObject *object,
78 static void gst_y4mencode_get_property (GObject *object,
83 static void gst_y4mencode_chain (GstPad *pad,
85 static GstElementStateReturn
86 gst_y4mencode_change_state (GstElement *element);
89 static GstElementClass *parent_class = NULL;
90 /*static guint gst_filter_signals[LAST_SIGNAL] = { 0 }; */
93 gst_y4mencode_get_type(void) {
94 static GType y4mencode_type = 0;
96 if (!y4mencode_type) {
97 static const GTypeInfo y4mencode_info = {
98 sizeof(GstY4mEncodeClass),
99 gst_y4mencode_base_init,
101 (GClassInitFunc)gst_y4mencode_class_init,
104 sizeof(GstY4mEncode),
106 (GInstanceInitFunc)gst_y4mencode_init,
108 y4mencode_type = g_type_register_static(GST_TYPE_ELEMENT,
112 return y4mencode_type;
117 gst_y4mencode_base_init (gpointer g_class)
119 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
121 gst_element_class_add_pad_template (element_class,
122 GST_PAD_TEMPLATE_GET (y4mencode_src_factory));
123 gst_element_class_add_pad_template (element_class,
124 GST_PAD_TEMPLATE_GET (y4mencode_sink_factory));
125 gst_element_class_set_details (element_class, &y4mencode_details);
128 gst_y4mencode_class_init (GstY4mEncodeClass *klass)
130 GObjectClass *gobject_class;
131 GstElementClass *gstelement_class;
133 gobject_class = (GObjectClass*)klass;
134 gstelement_class = (GstElementClass*)klass;
136 parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
138 gstelement_class->change_state = gst_y4mencode_change_state;
140 gobject_class->set_property = gst_y4mencode_set_property;
141 gobject_class->get_property = gst_y4mencode_get_property;
144 static GstPadLinkReturn
145 gst_y4mencode_sinkconnect (GstPad *pad, GstCaps *caps)
147 GstY4mEncode *filter;
150 float framerates[] = {
152 23.976, 24.000, /* 24fps movie */
154 29.970, 30.000, /* NTSC */
159 filter = GST_Y4MENCODE (gst_pad_get_parent (pad));
161 if (!GST_CAPS_IS_FIXED (caps))
162 return GST_PAD_LINK_DELAYED;
164 gst_caps_get_int (caps, "width", &filter->width);
165 gst_caps_get_int (caps, "height", &filter->height);
166 gst_caps_get_float (caps, "framerate", &fps);
169 for (i = 1; i < 9; i++) {
173 gfloat old_diff = fabs(framerates[idx] - fps),
174 new_diff = fabs(framerates[i] - fps);
176 if (new_diff < old_diff) {
181 filter->fps_idx = idx;
183 return GST_PAD_LINK_OK;
187 gst_y4mencode_init (GstY4mEncode *filter)
189 filter->sinkpad = gst_pad_new_from_template(
190 GST_PAD_TEMPLATE_GET (y4mencode_sink_factory), "sink");
191 gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
192 gst_pad_set_chain_function (filter->sinkpad, gst_y4mencode_chain);
193 gst_pad_set_link_function (filter->sinkpad, gst_y4mencode_sinkconnect);
195 filter->srcpad = gst_pad_new_from_template(
196 GST_PAD_TEMPLATE_GET (y4mencode_src_factory), "src");
197 gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
203 gst_y4mencode_chain (GstPad *pad,GstData *_data)
205 GstBuffer *buf = GST_BUFFER (_data);
206 GstY4mEncode *filter;
211 g_return_if_fail(pad != NULL);
212 g_return_if_fail(GST_IS_PAD(pad));
213 g_return_if_fail(buf != NULL);
215 filter = GST_Y4MENCODE (gst_pad_get_parent (pad));
216 g_return_if_fail(filter != NULL);
217 g_return_if_fail(GST_IS_Y4MENCODE(filter));
219 outbuf = gst_buffer_new ();
220 GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (buf) + 256);
223 header = "YUV4MPEG %d %d %d\nFRAME\n";
224 filter->init = FALSE;
230 snprintf (GST_BUFFER_DATA (outbuf), 255, header,
231 filter->width, filter->height, filter->fps_idx);
232 len = strlen (GST_BUFFER_DATA (outbuf));
234 memcpy (GST_BUFFER_DATA (outbuf) + len, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
235 GST_BUFFER_SIZE (outbuf) = GST_BUFFER_SIZE (buf) + len;
237 gst_buffer_unref(buf);
239 gst_pad_push(filter->srcpad,GST_DATA (outbuf));
243 gst_y4mencode_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
245 GstY4mEncode *filter;
247 /* it's not null if we got it, but it might not be ours */
248 g_return_if_fail(GST_IS_Y4MENCODE(object));
249 filter = GST_Y4MENCODE(object);
258 gst_y4mencode_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
260 GstY4mEncode *filter;
262 /* it's not null if we got it, but it might not be ours */
263 g_return_if_fail(GST_IS_Y4MENCODE(object));
264 filter = GST_Y4MENCODE(object);
268 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
273 static GstElementStateReturn
274 gst_y4mencode_change_state (GstElement *element)
276 GstY4mEncode *filter;
278 g_return_val_if_fail (GST_IS_Y4MENCODE (element), GST_STATE_FAILURE);
280 filter = GST_Y4MENCODE(element);
282 if (GST_STATE_TRANSITION (element) == GST_STATE_NULL_TO_READY) {
286 if (GST_ELEMENT_CLASS (parent_class)->change_state)
287 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
289 return GST_STATE_SUCCESS;
293 plugin_init (GstPlugin *plugin)
295 return gst_element_register (plugin, "y4menc", GST_RANK_NONE, GST_TYPE_Y4MENCODE);
302 "Encodes a YUV frame into the yuv4mpeg format (mjpegtools)",