updating some plugin categories
[platform/upstream/gst-plugins-good.git] / ext / jpeg / gstjpegdec.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 <string.h>
25
26 /*#define DEBUG_ENABLED*/
27 #include "gstjpegdec.h"
28
29 extern GstPadTemplate *jpegdec_src_template, *jpegdec_sink_template;
30
31 /* elementfactory information */
32 GstElementDetails gst_jpegdec_details = {
33   "jpeg image decoder",
34   "Codec/Image",
35   "LGPL",
36   ".jpeg",
37   VERSION,
38   "Wim Taymans <wim.taymans@tvd.be>",
39   "(C) 2000",
40 };
41
42 /* JpegDec signals and args */
43 enum {
44   /* FILL ME */
45   LAST_SIGNAL
46 };
47
48 enum {
49   ARG_0,
50   /* FILL ME */
51 };
52
53 static void     gst_jpegdec_class_init  (GstJpegDec *klass);
54 static void     gst_jpegdec_init        (GstJpegDec *jpegdec);
55
56 static void     gst_jpegdec_chain       (GstPad *pad, GstBuffer *buf);
57 static GstPadLinkReturn
58                 gst_jpegdec_link        (GstPad *pad, GstCaps *caps);
59
60 static GstElementClass *parent_class = NULL;
61 /*static guint gst_jpegdec_signals[LAST_SIGNAL] = { 0 }; */
62
63 GType
64 gst_jpegdec_get_type(void) {
65   static GType jpegdec_type = 0;
66
67   if (!jpegdec_type) {
68     static const GTypeInfo jpegdec_info = {
69       sizeof(GstJpegDec),      NULL,
70       NULL,
71       (GClassInitFunc)gst_jpegdec_class_init,
72       NULL,
73       NULL,
74       sizeof(GstJpegDec),
75       0,
76       (GInstanceInitFunc)gst_jpegdec_init,
77     };
78     jpegdec_type = g_type_register_static(GST_TYPE_ELEMENT, "GstJpegDec", &jpegdec_info, 0);
79   }
80   return jpegdec_type;
81 }
82
83 static void
84 gst_jpegdec_class_init (GstJpegDec *klass)
85 {
86   GstElementClass *gstelement_class;
87
88   gstelement_class = (GstElementClass*)klass;
89
90   parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
91 }
92
93 static void
94 gst_jpegdec_init_source (j_decompress_ptr cinfo)
95 {
96   GST_DEBUG ("gst_jpegdec_chain: init_source");
97 }
98 static gboolean
99 gst_jpegdec_fill_input_buffer (j_decompress_ptr cinfo)
100 {
101   GST_DEBUG ("gst_jpegdec_chain: fill_input_buffer");
102   return TRUE;
103 }
104
105 static void
106 gst_jpegdec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
107 {
108   GST_DEBUG ("gst_jpegdec_chain: skip_input_data");
109 }
110
111 static gboolean
112 gst_jpegdec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
113 {
114   GST_DEBUG ("gst_jpegdec_chain: resync_to_start");
115   return TRUE;
116 }
117
118 static void
119 gst_jpegdec_term_source (j_decompress_ptr cinfo)
120 {
121   GST_DEBUG ("gst_jpegdec_chain: term_source");
122 }
123
124 static void
125 gst_jpegdec_init (GstJpegDec *jpegdec)
126 {
127   GST_DEBUG ("gst_jpegdec_init: initializing");
128   /* create the sink and src pads */
129   jpegdec->sinkpad = gst_pad_new_from_template (jpegdec_sink_template, "sink");
130   gst_element_add_pad(GST_ELEMENT(jpegdec),jpegdec->sinkpad);
131   gst_pad_set_chain_function(jpegdec->sinkpad,gst_jpegdec_chain);
132   gst_pad_set_link_function(jpegdec->sinkpad, gst_jpegdec_link);
133   jpegdec->srcpad = gst_pad_new_from_template (jpegdec_src_template, "src");
134   gst_element_add_pad(GST_ELEMENT(jpegdec),jpegdec->srcpad);
135
136   /* initialize the jpegdec decoder state */
137   jpegdec->next_time = 0;
138
139   /* reset the initial video state */
140   jpegdec->format = -1;
141   jpegdec->width = -1;
142   jpegdec->height = -1;
143
144   jpegdec->line[0] = NULL;
145   jpegdec->line[1] = NULL;
146   jpegdec->line[2] = NULL;
147
148   /* setup jpeglib */
149   memset(&jpegdec->cinfo, 0, sizeof(jpegdec->cinfo));
150   memset(&jpegdec->jerr, 0, sizeof(jpegdec->jerr));
151   jpegdec->cinfo.err = jpeg_std_error(&jpegdec->jerr);
152   jpeg_create_decompress(&jpegdec->cinfo);
153
154   jpegdec->jsrc.init_source = gst_jpegdec_init_source;
155   jpegdec->jsrc.fill_input_buffer = gst_jpegdec_fill_input_buffer;
156   jpegdec->jsrc.skip_input_data = gst_jpegdec_skip_input_data;
157   jpegdec->jsrc.resync_to_restart = gst_jpegdec_resync_to_restart;
158   jpegdec->jsrc.term_source = gst_jpegdec_term_source;
159   jpegdec->cinfo.src = &jpegdec->jsrc;
160
161 }
162
163 static GstPadLinkReturn
164 gst_jpegdec_link (GstPad *pad, GstCaps *caps)
165 {
166   GstJpegDec *jpegdec = GST_JPEGDEC (gst_pad_get_parent (pad));
167
168   if (!GST_CAPS_IS_FIXED (caps))
169     return GST_PAD_LINK_DELAYED;
170
171   gst_caps_get (caps,
172                 "framerate", &jpegdec->fps,
173                 "width",     &jpegdec->width,
174                 "height",    &jpegdec->height,
175                 NULL);
176
177   caps = GST_CAPS_NEW ("jpegdec_srccaps",
178                        "video/x-raw-yuv",
179                          "format",    GST_PROPS_FOURCC (
180                            GST_MAKE_FOURCC ('I','4','2','0')),
181                          "width",     GST_PROPS_INT (jpegdec->width),
182                          "height",    GST_PROPS_INT (jpegdec->height),
183                          "framerate", GST_PROPS_FLOAT (jpegdec->fps));
184
185   return gst_pad_try_set_caps (jpegdec->srcpad, caps);
186 }
187
188 /* shamelessly ripped from jpegutils.c in mjpegtools */
189 static void add_huff_table (j_decompress_ptr dinfo,
190                             JHUFF_TBL **htblptr, 
191                             const UINT8 *bits, const UINT8 *val)
192 /* Define a Huffman table */
193 {
194   int nsymbols, len;
195
196   if (*htblptr == NULL)
197     *htblptr = jpeg_alloc_huff_table((j_common_ptr) dinfo);
198
199   /* Copy the number-of-symbols-of-each-code-length counts */
200   memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits));
201
202   /* Validate the counts.  We do this here mainly so we can copy the right
203    * number of symbols from the val[] array, without risking marching off
204    * the end of memory.  jchuff.c will do a more thorough test later.
205    */
206   nsymbols = 0;
207   for (len = 1; len <= 16; len++)
208     nsymbols += bits[len];
209   if (nsymbols < 1 || nsymbols > 256)
210     g_error("jpegutils.c:  add_huff_table failed badly. ");
211
212   memcpy((*htblptr)->huffval, val, nsymbols * sizeof(UINT8));
213 }
214
215
216
217 static void std_huff_tables (j_decompress_ptr dinfo)
218 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
219 /* IMPORTANT: these are only valid for 8-bit data precision! */
220 {
221   static const UINT8 bits_dc_luminance[17] =
222     { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
223   static const UINT8 val_dc_luminance[] =
224     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
225   
226   static const UINT8 bits_dc_chrominance[17] =
227     { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
228   static const UINT8 val_dc_chrominance[] =
229     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
230   
231   static const UINT8 bits_ac_luminance[17] =
232     { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
233   static const UINT8 val_ac_luminance[] =
234     { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
235       0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
236       0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
237       0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
238       0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
239       0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
240       0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
241       0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
242       0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
243       0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
244       0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
245       0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
246       0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
247       0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
248       0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
249       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
250       0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
251       0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
252       0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
253       0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
254       0xf9, 0xfa };
255   
256   static const UINT8 bits_ac_chrominance[17] =
257     { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
258   static const UINT8 val_ac_chrominance[] =
259     { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
260       0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
261       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
262       0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
263       0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
264       0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
265       0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
266       0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
267       0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
268       0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
269       0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
270       0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
271       0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
272       0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
273       0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
274       0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
275       0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
276       0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
277       0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
278       0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
279       0xf9, 0xfa };
280   
281   add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[0],
282                  bits_dc_luminance, val_dc_luminance);
283   add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[0],
284                  bits_ac_luminance, val_ac_luminance);
285   add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[1],
286                  bits_dc_chrominance, val_dc_chrominance);
287   add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[1],
288                  bits_ac_chrominance, val_ac_chrominance);
289 }
290
291
292
293 static void guarantee_huff_tables(j_decompress_ptr dinfo)
294 {
295   if ( (dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
296        (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
297        (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
298        (dinfo->ac_huff_tbl_ptrs[1] == NULL) ) {
299     GST_DEBUG (
300                "Generating standard Huffman tables for this frame.");
301     std_huff_tables(dinfo);
302   }
303 }
304
305 static void
306 gst_jpegdec_chain (GstPad *pad, GstBuffer *buf)
307 {
308   GstJpegDec *jpegdec;
309   guchar *data, *outdata;
310   gulong size, outsize;
311   GstBuffer *outbuf;
312   /*GstMeta *meta;*/
313   gint width, height, width2;
314   guchar *base[3];
315   gint i,j, k;
316   gint r_h, r_v;
317
318   g_return_if_fail(pad != NULL);
319   g_return_if_fail(GST_IS_PAD(pad));
320   g_return_if_fail(buf != NULL);
321   /*g_return_if_fail(GST_IS_BUFFER(buf));*/
322
323   jpegdec = GST_JPEGDEC (GST_OBJECT_PARENT (pad));
324
325   if (!GST_PAD_IS_LINKED (jpegdec->srcpad)) {
326     gst_buffer_unref (buf);
327     return;
328   }
329
330   data = (guchar *)GST_BUFFER_DATA(buf);
331   size = GST_BUFFER_SIZE(buf);
332   GST_DEBUG ("gst_jpegdec_chain: got buffer of %ld bytes in '%s'",size,
333           GST_OBJECT_NAME (jpegdec));
334
335   jpegdec->jsrc.next_input_byte = data;
336   jpegdec->jsrc.bytes_in_buffer = size;
337                                   
338
339   GST_DEBUG ("gst_jpegdec_chain: reading header %08lx", *(gulong *)data);
340   jpeg_read_header(&jpegdec->cinfo, TRUE);
341
342   r_h = jpegdec->cinfo.cur_comp_info[0]->h_samp_factor;
343   r_v = jpegdec->cinfo.cur_comp_info[0]->v_samp_factor;
344
345   /*g_print ("%d %d\n", r_h, r_v);*/
346   /*g_print ("%d %d\n", jpegdec->cinfo.cur_comp_info[1]->h_samp_factor, jpegdec->cinfo.cur_comp_info[1]->v_samp_factor);*/
347   /*g_print ("%d %d\n", jpegdec->cinfo.cur_comp_info[2]->h_samp_factor, jpegdec->cinfo.cur_comp_info[2]->v_samp_factor);*/
348
349   jpegdec->cinfo.do_fancy_upsampling = FALSE;
350   jpegdec->cinfo.do_block_smoothing = FALSE;
351   jpegdec->cinfo.out_color_space = JCS_YCbCr;
352   jpegdec->cinfo.dct_method = JDCT_IFAST;
353   jpegdec->cinfo.raw_data_out = TRUE;
354   GST_DEBUG ("gst_jpegdec_chain: starting decompress");
355   guarantee_huff_tables(&jpegdec->cinfo);
356   jpeg_start_decompress(&jpegdec->cinfo);
357   width = jpegdec->cinfo.output_width;
358   height = jpegdec->cinfo.output_height;
359   GST_DEBUG ("gst_jpegdec_chain: width %d, height %d", width, height);
360
361   outbuf = gst_buffer_new();
362   outsize = GST_BUFFER_SIZE(outbuf) = width*height +
363                                       width*height / 2;
364   outdata = GST_BUFFER_DATA(outbuf) = g_malloc(outsize);
365   GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf);
366
367   if (jpegdec->height != height) {
368     jpegdec->line[0] = g_realloc(jpegdec->line[0], height*sizeof(char*));
369     jpegdec->line[1] = g_realloc(jpegdec->line[1], height*sizeof(char*));
370     jpegdec->line[2] = g_realloc(jpegdec->line[2], height*sizeof(char*));
371     jpegdec->height = height;
372
373     gst_pad_try_set_caps (jpegdec->srcpad, 
374                           GST_CAPS_NEW (
375                             "jpegdec_caps",
376                             "video/x-raw-yuv",
377                               "format",    GST_PROPS_FOURCC (
378                                 GST_MAKE_FOURCC ('I','4','2','0')),
379                               "width",     GST_PROPS_INT (width),
380                               "height",    GST_PROPS_INT (height),
381                               "framerate", GST_PROPS_FLOAT (jpegdec->fps) 
382                           ));
383   }
384
385   /* mind the swap, jpeglib outputs blue chroma first */
386   base[0] = outdata;
387   base[1] = base[0]+width*height;
388   base[2] = base[1]+width*height/4;
389
390   width2 = width >> 1;
391
392   GST_DEBUG ("gst_jpegdec_chain: decompressing %u", jpegdec->cinfo.rec_outbuf_height);
393   for (i = 0; i < height; i += r_v*DCTSIZE) {
394     for (j=0, k=0; j< (r_v*DCTSIZE); j += r_v, k++) {
395       jpegdec->line[0][j]   = base[0]; base[0] += width;
396       if (r_v == 2) {
397          jpegdec->line[0][j+1] = base[0]; base[0] += width;
398       }
399       jpegdec->line[1][k]   = base[1]; 
400       jpegdec->line[2][k]   = base[2];
401       if (r_v == 2 || k&1) {
402          base[1] += width2; base[2] += width2;
403       }
404     }
405     /*g_print ("%d\n", jpegdec->cinfo.output_scanline);*/
406     jpeg_read_raw_data(&jpegdec->cinfo, jpegdec->line, r_v*DCTSIZE);
407   }
408
409   GST_DEBUG ("gst_jpegdec_chain: decompressing finished");
410   jpeg_finish_decompress(&jpegdec->cinfo);
411
412   GST_DEBUG ("gst_jpegdec_chain: sending buffer");
413   gst_pad_push(jpegdec->srcpad, outbuf);
414
415   gst_buffer_unref(buf);
416 }
417