compatibility fix for new GST_DEBUG stuff.
[platform/upstream/gstreamer.git] / ext / tarkin / gsttarkinenc.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "gsttarkinenc.h"
28
29 extern GstPadTemplate *enc_src_template, *enc_sink_template;
30
31 /* elementfactory information */
32 GstElementDetails tarkinenc_details = {
33   "Ogg Tarkin encoder",
34   "Filter/Video/Encoder",
35   "LGPL",
36   "Encodes video in OGG Tarkin format",
37   VERSION,
38   "Monty <monty@xiph.org>, " 
39   "Wim Taymans <wim.taymans@chello.be>",
40   "(C) 2002",
41 };
42
43 /* TarkinEnc signals and args */
44 enum
45 {
46   /* FILL ME */
47   LAST_SIGNAL
48 };
49
50 enum
51 {
52   ARG_0,
53   ARG_BITRATE,
54   ARG_S_MOMENTS,
55   ARG_A_MOMENTS,
56 };
57
58 static void     gst_tarkinenc_class_init        (TarkinEncClass *klass);
59 static void     gst_tarkinenc_init              (TarkinEnc *arkinenc);
60
61 static void     gst_tarkinenc_chain             (GstPad *pad, GstBuffer *buf);
62 static void     gst_tarkinenc_setup             (TarkinEnc *tarkinenc);
63
64 static void     gst_tarkinenc_get_property      (GObject *object, guint prop_id, GValue *value,
65                                                  GParamSpec *pspec);
66 static void     gst_tarkinenc_set_property      (GObject *object, guint prop_id, const GValue *value,
67                                                  GParamSpec *pspec);
68
69 static GstElementClass *parent_class = NULL;
70 /*static guint gst_tarkinenc_signals[LAST_SIGNAL] = { 0 }; */
71
72 GType
73 tarkinenc_get_type (void)
74 {
75   static GType tarkinenc_type = 0;
76
77   if (!tarkinenc_type) {
78     static const GTypeInfo tarkinenc_info = {
79       sizeof (TarkinEncClass), 
80       NULL,
81       NULL,
82       (GClassInitFunc) gst_tarkinenc_class_init,
83       NULL,
84       NULL,
85       sizeof (TarkinEnc),
86       0,
87       (GInstanceInitFunc) gst_tarkinenc_init,
88     };
89
90     tarkinenc_type = g_type_register_static (GST_TYPE_ELEMENT, "TarkinEnc", &tarkinenc_info, 0);
91   }
92   return tarkinenc_type;
93 }
94
95 static void
96 gst_tarkinenc_class_init (TarkinEncClass *klass)
97 {
98   GObjectClass *gobject_class;
99   GstElementClass *gstelement_class;
100
101   gobject_class = (GObjectClass *) klass;
102   gstelement_class = (GstElementClass *) klass;
103
104   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE, 
105     g_param_spec_int ("bitrate", "bitrate", "bitrate", 
106             G_MININT, G_MAXINT, 3000, G_PARAM_READWRITE));
107   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_S_MOMENTS, 
108     g_param_spec_int ("s_moments", "Synthesis Moments", 
109                       "Number of vanishing moments for the synthesis filter", 
110                       1, 4, 2, G_PARAM_READWRITE));
111   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_A_MOMENTS, 
112     g_param_spec_int ("a_moments", "Analysis Moments", 
113                       "Number of vanishing moments for the analysis filter", 
114                       1, 4, 2, G_PARAM_READWRITE));
115
116   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
117
118   gobject_class->set_property = gst_tarkinenc_set_property;
119   gobject_class->get_property = gst_tarkinenc_get_property;
120 }
121
122 static GstPadLinkReturn
123 gst_tarkinenc_sinkconnect (GstPad *pad, GstCaps *caps)
124 {
125   TarkinEnc *tarkinenc;
126
127   tarkinenc = GST_TARKINENC (gst_pad_get_parent (pad));
128
129   if (!GST_CAPS_IS_FIXED (caps))
130     return GST_PAD_LINK_DELAYED;
131
132   gst_caps_debug (caps, "caps to be set on tarkin sink pad");
133
134   tarkinenc->layer[0].bitstream_len = tarkinenc->bitrate;
135   tarkinenc->layer[0].a_moments = tarkinenc->a_moments;
136   tarkinenc->layer[0].s_moments = tarkinenc->s_moments;
137   gst_caps_get_int (caps, "width", &tarkinenc->layer[0].width);
138   gst_caps_get_int (caps, "height", &tarkinenc->layer[0].height);
139   tarkinenc->layer[0].format = TARKIN_RGB24;
140   tarkinenc->layer[0].frames_per_buf = TARKIN_RGB24;
141
142   gst_tarkinenc_setup (tarkinenc);
143
144   if (tarkinenc->setup)
145     return GST_PAD_LINK_OK;
146
147   return GST_PAD_LINK_REFUSED;
148 }
149
150 static void
151 gst_tarkinenc_init (TarkinEnc * tarkinenc)
152 {
153   tarkinenc->sinkpad = gst_pad_new_from_template (enc_sink_template, "sink");
154   gst_element_add_pad (GST_ELEMENT (tarkinenc), tarkinenc->sinkpad);
155   gst_pad_set_chain_function (tarkinenc->sinkpad, gst_tarkinenc_chain);
156   gst_pad_set_link_function (tarkinenc->sinkpad, gst_tarkinenc_sinkconnect);
157
158   tarkinenc->srcpad = gst_pad_new_from_template (enc_src_template, "src");
159   gst_element_add_pad (GST_ELEMENT (tarkinenc), tarkinenc->srcpad);
160
161   tarkinenc->bitrate = 3000;
162   tarkinenc->s_moments = 2;
163   tarkinenc->a_moments = 2;
164   tarkinenc->setup = FALSE;
165 }
166
167 TarkinError free_frame (void *s, void *ptr) 
168 {
169   return(TARKIN_OK);
170 }
171
172 TarkinError packet_out (void *stream, ogg_packet *op) 
173 {
174   ogg_page og;
175   TarkinStream *s = stream;
176   TarkinEnc *te = s->user_ptr;
177   GstBuffer *outbuf;
178
179   ogg_stream_packetin (&te->os, op);
180
181   if(op->e_o_s){
182     ogg_stream_flush (&te->os, &og);
183     outbuf = gst_buffer_new ();
184     GST_BUFFER_DATA (outbuf) = og.header;
185     GST_BUFFER_SIZE (outbuf) = og.header_len;
186     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
187     gst_pad_push (te->srcpad, outbuf);
188     outbuf = gst_buffer_new ();
189     GST_BUFFER_DATA (outbuf) = og.body;
190     GST_BUFFER_SIZE (outbuf) = og.body_len;
191     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
192     gst_pad_push (te->srcpad, outbuf);
193   } else {
194     while (ogg_stream_pageout (&te->os, &og)){
195       outbuf = gst_buffer_new ();
196       GST_BUFFER_DATA (outbuf) = og.header;
197       GST_BUFFER_SIZE (outbuf) = og.header_len;
198       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
199       gst_pad_push (te->srcpad, outbuf);
200       outbuf = gst_buffer_new ();
201       GST_BUFFER_DATA (outbuf) = og.body;
202       GST_BUFFER_SIZE (outbuf) = og.body_len;
203       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
204       gst_pad_push (te->srcpad, outbuf);
205     }
206   }
207   return (TARKIN_OK);
208 }
209
210
211 static void
212 gst_tarkinenc_setup (TarkinEnc *tarkinenc)
213 {
214   gint i;
215   GstBuffer *outbuf;
216
217   ogg_stream_init (&tarkinenc->os, 1);
218   tarkin_info_init (&tarkinenc->ti);
219
220   tarkinenc->ti.inter.numerator = 1;
221   tarkinenc->ti.inter.denominator = 1;
222   
223   tarkin_comment_init (&tarkinenc->tc);
224   tarkin_comment_add_tag (&tarkinenc->tc, "TITLE", "GStreamer produced file");
225   tarkin_comment_add_tag (&tarkinenc->tc, "ARTIST", "C coders ;)");
226
227   tarkinenc->tarkin_stream = tarkin_stream_new ();
228   tarkin_analysis_init (tarkinenc->tarkin_stream, 
229                         &tarkinenc->ti, free_frame, packet_out, (void*)tarkinenc);
230   tarkin_analysis_add_layer(tarkinenc->tarkin_stream, &tarkinenc->layer[0]);
231
232   tarkin_analysis_headerout (tarkinenc->tarkin_stream, &tarkinenc->tc, 
233                   tarkinenc->op, &tarkinenc->op[1], &tarkinenc->op[2]);
234   for(i = 0; i < 3; i++){
235     ogg_stream_packetin(&tarkinenc->os, &tarkinenc->op[i]);
236   }
237
238   ogg_stream_flush (&tarkinenc->os, &tarkinenc->og);
239
240   tarkinenc->frame_num = 0;
241
242   outbuf = gst_buffer_new ();
243   GST_BUFFER_DATA (outbuf) = tarkinenc->og.header;
244   GST_BUFFER_SIZE (outbuf) = tarkinenc->og.header_len;
245   GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
246   gst_pad_push (tarkinenc->srcpad, outbuf);
247
248   outbuf = gst_buffer_new ();
249   GST_BUFFER_DATA (outbuf) = tarkinenc->og.body;
250   GST_BUFFER_SIZE (outbuf) = tarkinenc->og.body_len;
251   GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
252   gst_pad_push (tarkinenc->srcpad, outbuf);
253
254   tarkinenc->setup = TRUE;
255 }
256
257 static void
258 gst_tarkinenc_chain (GstPad *pad, GstBuffer *buf)
259 {
260   TarkinEnc *tarkinenc;
261
262   g_return_if_fail (pad != NULL);
263   g_return_if_fail (GST_IS_PAD (pad));
264   g_return_if_fail (buf != NULL);
265
266   tarkinenc = GST_TARKINENC (gst_pad_get_parent (pad));
267
268   if (!tarkinenc->setup) {
269     gst_element_error (GST_ELEMENT (tarkinenc), "encoder not initialized (input is not audio?)");
270     if (GST_IS_BUFFER (buf))
271       gst_buffer_unref (buf);
272     else
273       gst_pad_event_default (pad, GST_EVENT (buf));
274     return;
275   }
276
277   if (GST_IS_EVENT (buf)) {
278     switch (GST_EVENT_TYPE (buf)) {
279       case GST_EVENT_EOS:
280         tarkin_analysis_framein (tarkinenc->tarkin_stream, NULL, 0, NULL); /* EOS */
281         tarkin_comment_clear (&tarkinenc->tc);
282         tarkin_stream_destroy (tarkinenc->tarkin_stream);
283       default:
284         gst_pad_event_default (pad, GST_EVENT (buf));
285         break;
286     }
287   }
288   else {
289     gchar *data;
290     gulong size;
291     TarkinTime date;
292   
293     /* data to encode */
294     data = GST_BUFFER_DATA (buf);
295     size = GST_BUFFER_SIZE (buf);
296
297     date.numerator = tarkinenc->frame_num;
298     date.denominator = 1;
299     tarkin_analysis_framein (tarkinenc->tarkin_stream, data, 0, &date);
300     tarkinenc->frame_num++;
301
302     gst_buffer_unref (buf);
303   }
304 }
305
306 static void
307 gst_tarkinenc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
308 {
309   TarkinEnc *tarkinenc;
310
311   /* it's not null if we got it, but it might not be ours */
312   g_return_if_fail (GST_IS_TARKINENC (object));
313
314   tarkinenc = GST_TARKINENC (object);
315
316   switch (prop_id) {
317     case ARG_BITRATE:
318       g_value_set_int (value, tarkinenc->bitrate);
319       break;
320     case ARG_S_MOMENTS:
321       g_value_set_int (value, tarkinenc->s_moments);
322       break;
323     case ARG_A_MOMENTS:
324       g_value_set_int (value, tarkinenc->a_moments);
325       break;
326     default:
327       break;
328   }
329 }
330
331 static void
332 gst_tarkinenc_set_property (GObject *object, guint prop_id, const GValue *value,
333                             GParamSpec *pspec)
334 {
335   TarkinEnc *tarkinenc;
336
337   /* it's not null if we got it, but it might not be ours */
338   g_return_if_fail (GST_IS_TARKINENC (object));
339
340   tarkinenc = GST_TARKINENC (object);
341
342   switch (prop_id) {
343     case ARG_BITRATE:
344       tarkinenc->bitrate = g_value_get_int (value);
345       break;
346     case ARG_S_MOMENTS:
347     {
348       gint s_moments;
349
350       s_moments = g_value_get_int (value);
351       if (s_moments != 1 || s_moments != 2 || s_moments != 4) {
352         g_warning ("tarkinenc: s_moments must be 1, 2 or 4");
353       }
354       else {
355         tarkinenc->s_moments = s_moments;
356       }
357       break;
358     }
359     case ARG_A_MOMENTS:
360     {
361       gint a_moments;
362
363       a_moments = g_value_get_int (value);
364       if (a_moments != 1 || a_moments != 2 || a_moments != 4) {
365         g_warning ("tarkinenc: a_moments must be 1, 2 or 4");
366       }
367       else {
368         tarkinenc->a_moments = a_moments;
369       }
370       break;
371     }
372     default:
373       break;
374   }
375 }