9dfab51eb73c32169224777ebff10f00aca415aa
[platform/upstream/gstreamer.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 #include <string.h>
22
23 /*#define DEBUG_ENABLED*/
24 #include "gstjpegdec.h"
25
26 extern GstPadTemplate *jpegdec_src_template, *jpegdec_sink_template;
27
28 /* elementfactory information */
29 GstElementDetails gst_jpegdec_details = {
30   "jpeg image decoder",
31   "Filter/Decoder/Image",
32   ".jpeg",
33   VERSION,
34   "Wim Taymans <wim.taymans@tvd.be>",
35   "(C) 2000",
36 };
37
38 /* JpegDec signals and args */
39 enum {
40   /* FILL ME */
41   LAST_SIGNAL
42 };
43
44 enum {
45   ARG_0,
46   /* FILL ME */
47 };
48
49 static void     gst_jpegdec_class_init  (GstJpegDec *klass);
50 static void     gst_jpegdec_init        (GstJpegDec *jpegdec);
51
52 static void     gst_jpegdec_chain       (GstPad *pad, GstBuffer *buf);
53
54 static GstElementClass *parent_class = NULL;
55 /*static guint gst_jpegdec_signals[LAST_SIGNAL] = { 0 }; */
56
57 GType
58 gst_jpegdec_get_type(void) {
59   static GType jpegdec_type = 0;
60
61   if (!jpegdec_type) {
62     static const GTypeInfo jpegdec_info = {
63       sizeof(GstJpegDec),      NULL,
64       NULL,
65       (GClassInitFunc)gst_jpegdec_class_init,
66       NULL,
67       NULL,
68       sizeof(GstJpegDec),
69       0,
70       (GInstanceInitFunc)gst_jpegdec_init,
71     };
72     jpegdec_type = g_type_register_static(GST_TYPE_ELEMENT, "GstJpegDec", &jpegdec_info, 0);
73   }
74   return jpegdec_type;
75 }
76
77 static void
78 gst_jpegdec_class_init (GstJpegDec *klass)
79 {
80   GstElementClass *gstelement_class;
81
82   gstelement_class = (GstElementClass*)klass;
83
84   parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
85 }
86
87 static void
88 gst_jpegdec_init_source (j_decompress_ptr cinfo)
89 {
90   GST_DEBUG (0,"gst_jpegdec_chain: init_source\n");
91 }
92 static gboolean
93 gst_jpegdec_fill_input_buffer (j_decompress_ptr cinfo)
94 {
95   GST_DEBUG (0,"gst_jpegdec_chain: fill_input_buffer\n");
96   return TRUE;
97 }
98
99 static void
100 gst_jpegdec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
101 {
102   GST_DEBUG (0,"gst_jpegdec_chain: skip_input_data\n");
103 }
104
105 static gboolean
106 gst_jpegdec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
107 {
108   GST_DEBUG (0,"gst_jpegdec_chain: resync_to_start\n");
109   return TRUE;
110 }
111
112 static void
113 gst_jpegdec_term_source (j_decompress_ptr cinfo)
114 {
115   GST_DEBUG (0,"gst_jpegdec_chain: term_source\n");
116 }
117
118 static void
119 gst_jpegdec_init (GstJpegDec *jpegdec)
120 {
121   GST_DEBUG (0,"gst_jpegdec_init: initializing\n");
122   /* create the sink and src pads */
123   jpegdec->sinkpad = gst_pad_new_from_template (jpegdec_sink_template, "sink");
124   gst_element_add_pad(GST_ELEMENT(jpegdec),jpegdec->sinkpad);
125   gst_pad_set_chain_function(jpegdec->sinkpad,gst_jpegdec_chain);
126   jpegdec->srcpad = gst_pad_new_from_template (jpegdec_src_template, "src");
127   gst_element_add_pad(GST_ELEMENT(jpegdec),jpegdec->srcpad);
128
129   /* initialize the jpegdec decoder state */
130   jpegdec->next_time = 0;
131
132   /* reset the initial video state */
133   jpegdec->format = -1;
134   jpegdec->width = -1;
135   jpegdec->height = -1;
136
137   jpegdec->line[0] = NULL;
138   jpegdec->line[1] = NULL;
139   jpegdec->line[2] = NULL;
140
141   /* setup jpeglib */
142   memset(&jpegdec->cinfo, 0, sizeof(jpegdec->cinfo));
143   memset(&jpegdec->jerr, 0, sizeof(jpegdec->jerr));
144   jpegdec->cinfo.err = jpeg_std_error(&jpegdec->jerr);
145   jpeg_create_decompress(&jpegdec->cinfo);
146
147   jpegdec->jsrc.init_source = gst_jpegdec_init_source;
148   jpegdec->jsrc.fill_input_buffer = gst_jpegdec_fill_input_buffer;
149   jpegdec->jsrc.skip_input_data = gst_jpegdec_skip_input_data;
150   jpegdec->jsrc.resync_to_restart = gst_jpegdec_resync_to_restart;
151   jpegdec->jsrc.term_source = gst_jpegdec_term_source;
152   jpegdec->cinfo.src = &jpegdec->jsrc;
153
154 }
155
156 static void
157 gst_jpegdec_chain (GstPad *pad, GstBuffer *buf)
158 {
159   GstJpegDec *jpegdec;
160   guchar *data, *outdata;
161   gulong size, outsize;
162   GstBuffer *outbuf;
163   /*GstMeta *meta;*/
164   gint width, height, width2;
165   guchar *base[3];
166   gint i,j, k;
167   gint r_h, r_v;
168
169   g_return_if_fail(pad != NULL);
170   g_return_if_fail(GST_IS_PAD(pad));
171   g_return_if_fail(buf != NULL);
172   /*g_return_if_fail(GST_IS_BUFFER(buf));*/
173
174   jpegdec = GST_JPEGDEC (GST_OBJECT_PARENT (pad));
175
176   if (!GST_PAD_IS_CONNECTED (jpegdec->srcpad)) {
177     gst_buffer_unref (buf);
178     return;
179   }
180
181   data = (guchar *)GST_BUFFER_DATA(buf);
182   size = GST_BUFFER_SIZE(buf);
183   GST_DEBUG (0,"gst_jpegdec_chain: got buffer of %ld bytes in '%s'\n",size,
184           GST_OBJECT_NAME (jpegdec));
185
186   jpegdec->jsrc.next_input_byte = data;
187   jpegdec->jsrc.bytes_in_buffer = size;
188                                   
189
190   GST_DEBUG (0,"gst_jpegdec_chain: reading header %08lx\n", *(gulong *)data);
191   jpeg_read_header(&jpegdec->cinfo, TRUE);
192
193   r_h = jpegdec->cinfo.cur_comp_info[0]->h_samp_factor;
194   r_v = jpegdec->cinfo.cur_comp_info[0]->v_samp_factor;
195
196   /*g_print ("%d %d\n", r_h, r_v);*/
197   /*g_print ("%d %d\n", jpegdec->cinfo.cur_comp_info[1]->h_samp_factor, jpegdec->cinfo.cur_comp_info[1]->v_samp_factor);*/
198   /*g_print ("%d %d\n", jpegdec->cinfo.cur_comp_info[2]->h_samp_factor, jpegdec->cinfo.cur_comp_info[2]->v_samp_factor);*/
199
200   jpegdec->cinfo.do_fancy_upsampling = FALSE;
201   jpegdec->cinfo.do_block_smoothing = FALSE;
202   jpegdec->cinfo.out_color_space = JCS_YCbCr;
203   jpegdec->cinfo.dct_method = JDCT_IFAST;
204   jpegdec->cinfo.raw_data_out = TRUE;
205   GST_DEBUG (0,"gst_jpegdec_chain: starting decompress\n");
206   jpeg_start_decompress(&jpegdec->cinfo);
207   width = jpegdec->cinfo.output_width;
208   height = jpegdec->cinfo.output_height;
209   GST_DEBUG (0,"gst_jpegdec_chain: width %d, height %d\n", width, height);
210
211   outbuf = gst_buffer_new();
212   outsize = GST_BUFFER_SIZE(outbuf) = width*height +
213                                       width*height / 2;
214   outdata = GST_BUFFER_DATA(outbuf) = g_malloc(outsize);
215   GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf);
216
217   if (jpegdec->height != height) {
218     jpegdec->line[0] = g_realloc(jpegdec->line[0], height*sizeof(char*));
219     jpegdec->line[1] = g_realloc(jpegdec->line[1], height*sizeof(char*));
220     jpegdec->line[2] = g_realloc(jpegdec->line[2], height*sizeof(char*));
221     jpegdec->height = height;
222
223     gst_pad_try_set_caps (jpegdec->srcpad, 
224                           GST_CAPS_NEW (
225                             "jpegdec_caps",
226                             "video/raw",
227                               "format",  GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')),
228                               "width",   GST_PROPS_INT (width),
229                               "height",  GST_PROPS_INT (height)
230                           ));
231   }
232
233   /* mind the swap, jpeglib outputs blue chroma first */
234   base[0] = outdata;
235   base[1] = base[0]+width*height;
236   base[2] = base[1]+width*height/4;
237
238   width2 = width >> 1;
239
240   GST_DEBUG (0,"gst_jpegdec_chain: decompressing %u\n", jpegdec->cinfo.rec_outbuf_height);
241   for (i = 0; i < height; i += r_v*DCTSIZE) {
242     for (j=0, k=0; j< (r_v*DCTSIZE); j += r_v, k++) {
243       jpegdec->line[0][j]   = base[0]; base[0] += width;
244       if (r_v == 2) {
245          jpegdec->line[0][j+1] = base[0]; base[0] += width;
246       }
247       jpegdec->line[1][k]   = base[1]; 
248       jpegdec->line[2][k]   = base[2];
249       if (r_v == 2 || k&1) {
250          base[1] += width2; base[2] += width2;
251       }
252     }
253     /*g_print ("%d\n", jpegdec->cinfo.output_scanline);*/
254     jpeg_read_raw_data(&jpegdec->cinfo, jpegdec->line, r_v*DCTSIZE);
255   }
256
257   GST_DEBUG (0,"gst_jpegdec_chain: decompressing finished\n");
258   jpeg_finish_decompress(&jpegdec->cinfo);
259
260   GST_DEBUG (0,"gst_jpegdec_chain: sending buffer\n");
261   gst_pad_push(jpegdec->srcpad, outbuf);
262
263   gst_buffer_unref(buf);
264 }
265