Fix crash with partial fribidi conversion.
[mplayer/greg.git] / libmpcodecs / vd_ijpg.c
bloba54b339c8f0617f37761c1d891f4c3acc4d05327
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
6 #include "config.h"
7 #include "mp_msg.h"
9 #include <jpeglib.h>
10 #define UINT16 IJPG_UINT16
11 #define INT16 IJPG_INT16
13 #include <setjmp.h>
15 #include "mpbswap.h"
17 #include "vd_internal.h"
19 static vd_info_t info = {
20 "JPEG Images decoder",
21 "ijpg",
22 "Pontscho",
23 "based on vd_mpng.c",
24 "uses Independent JPEG Group's jpeglib"
27 LIBVD_EXTERN(ijpg)
29 static int last_w=-1;
30 static int last_h=-1;
31 static int last_depth=-1;
33 // to set/get/query special features/parameters
34 static int control(sh_video_t *sh,int cmd,void* arg,...){
35 if (cmd == VDCTRL_QUERY_FORMAT) {
36 int format = *(int *)arg;
37 if ((last_depth == 24 && format == IMGFMT_RGB24) ||
38 (last_depth == 8 && format == IMGFMT_Y8 ))
39 return CONTROL_TRUE;
40 return CONTROL_FALSE;
42 return CONTROL_UNKNOWN;
45 // init driver
46 static int init(sh_video_t *sh){
47 last_w=-1;
48 return 1;
51 // uninit driver
52 static void uninit(sh_video_t *sh){
55 //mp_image_t* mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag, int w, int h);
57 typedef struct
59 struct jpeg_source_mgr pub;
60 unsigned char * inbuf;
61 int bufsize;
62 } my_source_mgr;
64 typedef my_source_mgr * my_src_ptr;
66 METHODDEF(void) init_source (j_decompress_ptr cinfo)
70 METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo)
72 my_src_ptr src = (my_src_ptr) cinfo->src;
73 src->pub.next_input_byte = src->inbuf;
74 src->pub.bytes_in_buffer = src->bufsize;
75 return TRUE;
78 METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes)
80 my_src_ptr src = (my_src_ptr) cinfo->src;
82 if (num_bytes > 0)
84 while (num_bytes > (long) src->pub.bytes_in_buffer)
86 num_bytes -= (long) src->pub.bytes_in_buffer;
87 (void) fill_input_buffer(cinfo);
89 src->pub.next_input_byte += (size_t) num_bytes;
90 src->pub.bytes_in_buffer -= (size_t) num_bytes;
94 METHODDEF(void) term_source (j_decompress_ptr cinfo) { }
96 GLOBAL(void) jpeg_buf_src ( j_decompress_ptr cinfo, char * inbuf,int bufsize )
98 my_src_ptr src;
99 if (cinfo->src == NULL) cinfo->src=malloc( sizeof( my_source_mgr ) );
100 src = (my_src_ptr) cinfo->src;
101 src->pub.init_source = init_source;
102 src->pub.fill_input_buffer = fill_input_buffer;
103 src->pub.skip_input_data = skip_input_data;
104 src->pub.resync_to_restart = jpeg_resync_to_restart;
105 src->pub.term_source = term_source;
106 src->inbuf = inbuf;
107 src->bufsize=bufsize;
108 src->pub.bytes_in_buffer = 0;
109 src->pub.next_input_byte = NULL;
112 struct my_error_mgr
114 struct jpeg_error_mgr pub;
115 jmp_buf setjmp_buffer;
118 typedef struct my_error_mgr * my_error_ptr;
120 METHODDEF(void) my_error_exit (j_common_ptr cinfo)
122 my_error_ptr myerr=(my_error_ptr) cinfo->err;
123 (*cinfo->err->output_message) (cinfo);
124 longjmp(myerr->setjmp_buffer, 1);
127 // decode a frame
128 static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
129 struct jpeg_decompress_struct cinfo;
130 struct my_error_mgr jerr;
131 mp_image_t * mpi = NULL;
132 int width,height,depth,i;
134 if ( len <= 0 ) return NULL; // skipped frame
136 memset(&cinfo, 0, sizeof(cinfo));
137 memset(&jerr, 0, sizeof(jerr));
138 cinfo.err=jpeg_std_error( &jerr.pub );
139 jerr.pub.error_exit=my_error_exit;
140 if( setjmp( jerr.setjmp_buffer ) )
142 mp_msg( MSGT_DECVIDEO,MSGL_ERR,"[ijpg] setjmp error ...\n" );
143 return NULL;
146 jpeg_create_decompress( &cinfo );
147 jpeg_buf_src( &cinfo,data,len );
148 jpeg_read_header( &cinfo,TRUE );
149 sh->disp_w=width=cinfo.image_width;
150 sh->disp_h=height=cinfo.image_height;
151 jpeg_start_decompress( &cinfo );
152 depth=cinfo.output_components * 8;
154 switch( depth ) {
155 case 8:
156 case 24: break;
157 default: mp_msg( MSGT_DECVIDEO,MSGL_ERR,"Sorry, unsupported JPEG colorspace: %d.\n",depth ); return NULL;
160 if ( last_w!=width || last_h!=height || last_depth != depth )
162 last_depth = depth;
163 if(!mpcodecs_config_vo( sh,width,height, depth == 8 ? IMGFMT_Y8 : IMGFMT_RGB24 )) return NULL;
164 last_w=width; last_h=height;
167 mpi=mpcodecs_get_image( sh,MP_IMGTYPE_TEMP,MP_IMGFLAG_ACCEPT_STRIDE,width,height );
168 if ( !mpi ) return NULL;
170 for ( i=0;i < height;i++ )
172 unsigned char * drow = mpi->planes[0] + mpi->stride[0] * i;
173 jpeg_read_scanlines( &cinfo,(JSAMPLE**)&drow,1 );
176 jpeg_finish_decompress(&cinfo);
177 jpeg_destroy_decompress(&cinfo);
179 return mpi;