10l initial patch by Oded Shimon <ods15 at ods15.dyndns.org>
[mplayer/greg.git] / libmpcodecs / vd_ijpg.c
blobe4c127a0da13ec0e3b41f2e9db5a327cef97ec8a
2 #include <stdio.h>
3 #include <stdlib.h>
5 #include "config.h"
6 #include "mp_msg.h"
8 #include <jpeglib.h>
9 #define UINT16 IJPG_UINT16
10 #define INT16 IJPG_INT16
12 #include <setjmp.h>
14 #include "bswap.h"
15 #include "postproc/rgb2rgb.h"
16 #include "libvo/fastmemcpy.h"
18 #include "vd_internal.h"
20 static vd_info_t info = {
21 "JPEG Images decoder",
22 "ijpg",
23 "Pontscho",
24 "based on vd_mpng.c",
25 "uses Indipended JPEG Group's jpeglib"
28 LIBVD_EXTERN(ijpg)
30 static int last_w=-1;
31 static int last_h=-1;
33 // to set/get/query special features/parameters
34 static int control(sh_video_t *sh,int cmd,void* arg,...){
35 return CONTROL_UNKNOWN;
38 // init driver
39 static int init(sh_video_t *sh){
40 last_w=-1;
41 return 1;
44 // uninit driver
45 static void uninit(sh_video_t *sh){
48 //mp_image_t* mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag, int w, int h);
50 typedef struct
52 struct jpeg_source_mgr pub;
53 unsigned char * inbuf;
54 int bufsize;
55 } my_source_mgr;
57 typedef my_source_mgr * my_src_ptr;
59 METHODDEF(void) init_source (j_decompress_ptr cinfo)
63 METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo)
65 my_src_ptr src = (my_src_ptr) cinfo->src;
66 src->pub.next_input_byte = src->inbuf;
67 src->pub.bytes_in_buffer = src->bufsize;
68 return TRUE;
71 METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes)
73 my_src_ptr src = (my_src_ptr) cinfo->src;
75 if (num_bytes > 0)
77 while (num_bytes > (long) src->pub.bytes_in_buffer)
79 num_bytes -= (long) src->pub.bytes_in_buffer;
80 (void) fill_input_buffer(cinfo);
82 src->pub.next_input_byte += (size_t) num_bytes;
83 src->pub.bytes_in_buffer -= (size_t) num_bytes;
87 METHODDEF(void) term_source (j_decompress_ptr cinfo) { }
89 GLOBAL(void) jpeg_buf_src ( j_decompress_ptr cinfo, char * inbuf,int bufsize )
91 my_src_ptr src;
92 if (cinfo->src == NULL) cinfo->src=malloc( sizeof( my_source_mgr ) );
93 src = (my_src_ptr) cinfo->src;
94 src->pub.init_source = init_source;
95 src->pub.fill_input_buffer = fill_input_buffer;
96 src->pub.skip_input_data = skip_input_data;
97 src->pub.resync_to_restart = jpeg_resync_to_restart;
98 src->pub.term_source = term_source;
99 src->inbuf = inbuf;
100 src->bufsize=bufsize;
101 src->pub.bytes_in_buffer = 0;
102 src->pub.next_input_byte = NULL;
105 struct my_error_mgr
107 struct jpeg_error_mgr pub;
108 jmp_buf setjmp_buffer;
111 typedef struct my_error_mgr * my_error_ptr;
113 METHODDEF(void) my_error_exit (j_common_ptr cinfo)
115 my_error_ptr myerr=(my_error_ptr) cinfo->err;
116 (*cinfo->err->output_message) (cinfo);
117 longjmp(myerr->setjmp_buffer, 1);
120 static struct jpeg_decompress_struct cinfo;
121 static struct my_error_mgr jerr;
122 static int row_stride;
123 static unsigned char *temp_row=NULL;
125 // decode a frame
126 static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
127 mp_image_t * mpi = NULL;
128 int width,height,depth,i;
130 if ( len <= 0 ) return NULL; // skipped frame
132 cinfo.err=jpeg_std_error( &jerr.pub );
133 jerr.pub.error_exit=my_error_exit;
134 if( setjmp( jerr.setjmp_buffer ) )
136 mp_msg( MSGT_DECVIDEO,MSGL_ERR,"[ijpg] setjmp error ...\n" );
137 return NULL;
140 jpeg_create_decompress( &cinfo );
141 jpeg_buf_src( &cinfo,data,len );
142 jpeg_read_header( &cinfo,TRUE );
143 sh->disp_w=width=cinfo.image_width;
144 sh->disp_h=height=cinfo.image_height;
145 jpeg_start_decompress( &cinfo );
146 depth=cinfo.output_components * 8;
148 switch( depth ) {
149 case 8:
150 case 24: break;
151 default: mp_msg( MSGT_DECVIDEO,MSGL_ERR,"Sorry, unsupported JPEG colorspace: %d.\n",depth ); return NULL;
154 if ( last_w!=width || last_h!=height )
156 if(!mpcodecs_config_vo( sh,width,height, IMGFMT_RGB24 )) return NULL;
157 if(temp_row) free(temp_row);
158 temp_row=malloc(3*width+16);
159 last_w=width; last_h=height;
162 mpi=mpcodecs_get_image( sh,MP_IMGTYPE_TEMP,MP_IMGFLAG_ACCEPT_STRIDE,width,height );
163 if ( !mpi ) return NULL;
165 row_stride=cinfo.output_width * cinfo.output_components;
167 for ( i=0;i < height;i++ )
169 unsigned char * drow = mpi->planes[0] + mpi->stride[0] * i;
170 unsigned char * row = (mpi->imgfmt==IMGFMT_RGB24 && depth==24) ? drow : temp_row;
171 jpeg_read_scanlines( &cinfo,(JSAMPLE**)&row,1 );
172 if(depth==8){
173 // grayscale -> rgb/bgr 24/32
174 int x;
175 if(mpi->bpp==32)
176 for(x=0;x<width;x++) drow[4*x]=0x010101*row[x];
177 else
178 for(x=0;x<width;x++) drow[3*x+0]=drow[3*x+1]=drow[3*x+2]=row[x];
179 } else {
180 int x;
181 switch(mpi->imgfmt){
182 // rgb24 -> bgr24
183 case IMGFMT_BGR24:
184 for(x=0;x<3*width;x+=3){
185 drow[x+0]=row[x+2];
186 drow[x+1]=row[x+1];
187 drow[x+2]=row[x+0];
189 break;
190 // rgb24 -> bgr32
191 case IMGFMT_BGR32:
192 for(x=0;x<width;x++){
193 drow[4*x+0]=row[3*x+2];
194 drow[4*x+1]=row[3*x+1];
195 drow[4*x+2]=row[3*x+0];
197 break;
202 jpeg_finish_decompress(&cinfo);
203 jpeg_destroy_decompress(&cinfo);
205 return mpi;