docs: document --quvi-format
[mplayer.git] / libmpcodecs / vd_ijpg.c
blob2bfefb405dc404888fed5f1d0d2458c9d8c0f85e
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer 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
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
23 #include "config.h"
24 #include "mp_msg.h"
26 #include <jpeglib.h>
27 #define UINT16 IJPG_UINT16
28 #define INT16 IJPG_INT16
30 #include <setjmp.h>
32 #include "mpbswap.h"
34 #include "vd_internal.h"
36 static const vd_info_t info = {
37 "JPEG Images decoder",
38 "ijpg",
39 "Pontscho",
40 "based on vd_mpng.c",
41 "uses Independent JPEG Group's jpeglib"
44 LIBVD_EXTERN(ijpg)
46 static int last_w=-1;
47 static int last_h=-1;
48 static int last_depth=-1;
50 // to set/get/query special features/parameters
51 static int control(sh_video_t *sh,int cmd,void* arg,...){
52 if (cmd == VDCTRL_QUERY_FORMAT) {
53 int format = *(int *)arg;
54 if ((last_depth == 24 && format == IMGFMT_RGB24) ||
55 (last_depth == 8 && format == IMGFMT_Y8 ))
56 return CONTROL_TRUE;
57 return CONTROL_FALSE;
59 return CONTROL_UNKNOWN;
62 // init driver
63 static int init(sh_video_t *sh){
64 last_w=-1;
65 return 1;
68 // uninit driver
69 static void uninit(sh_video_t *sh){
72 //mp_image_t* mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag, int w, int h);
74 typedef struct
76 struct jpeg_source_mgr pub;
77 unsigned char * inbuf;
78 int bufsize;
79 } my_source_mgr;
81 typedef my_source_mgr * my_src_ptr;
83 METHODDEF(void) init_source (j_decompress_ptr cinfo)
87 METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo)
89 my_src_ptr src = (my_src_ptr) cinfo->src;
90 src->pub.next_input_byte = src->inbuf;
91 src->pub.bytes_in_buffer = src->bufsize;
92 return TRUE;
95 METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes)
97 my_src_ptr src = (my_src_ptr) cinfo->src;
99 if (num_bytes > 0)
101 while (num_bytes > (long) src->pub.bytes_in_buffer)
103 num_bytes -= (long) src->pub.bytes_in_buffer;
104 (void) fill_input_buffer(cinfo);
106 src->pub.next_input_byte += (size_t) num_bytes;
107 src->pub.bytes_in_buffer -= (size_t) num_bytes;
111 METHODDEF(void) term_source (j_decompress_ptr cinfo) { }
113 static void jpeg_buf_src (j_decompress_ptr cinfo, char * inbuf, int bufsize)
115 my_src_ptr src;
116 if (cinfo->src == NULL) cinfo->src=malloc( sizeof( my_source_mgr ) );
117 src = (my_src_ptr) cinfo->src;
118 src->pub.init_source = init_source;
119 src->pub.fill_input_buffer = fill_input_buffer;
120 src->pub.skip_input_data = skip_input_data;
121 src->pub.resync_to_restart = jpeg_resync_to_restart;
122 src->pub.term_source = term_source;
123 src->inbuf = inbuf;
124 src->bufsize=bufsize;
125 src->pub.bytes_in_buffer = 0;
126 src->pub.next_input_byte = NULL;
129 struct my_error_mgr
131 struct jpeg_error_mgr pub;
132 jmp_buf setjmp_buffer;
135 typedef struct my_error_mgr * my_error_ptr;
137 METHODDEF(void) my_error_exit (j_common_ptr cinfo)
139 my_error_ptr myerr=(my_error_ptr) cinfo->err;
140 (*cinfo->err->output_message) (cinfo);
141 longjmp(myerr->setjmp_buffer, 1);
144 // decode a frame
145 static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
146 struct jpeg_decompress_struct cinfo;
147 struct my_error_mgr jerr;
148 mp_image_t * mpi = NULL;
149 int width,height,depth,i;
151 if ( len <= 0 ) return NULL; // skipped frame
153 memset(&cinfo, 0, sizeof(cinfo));
154 memset(&jerr, 0, sizeof(jerr));
155 cinfo.err=jpeg_std_error( &jerr.pub );
156 jerr.pub.error_exit=my_error_exit;
157 if( setjmp( jerr.setjmp_buffer ) )
159 mp_msg( MSGT_DECVIDEO,MSGL_ERR,"[ijpg] setjmp error ...\n" );
160 return NULL;
163 jpeg_create_decompress( &cinfo );
164 jpeg_buf_src( &cinfo,data,len );
165 jpeg_read_header( &cinfo,TRUE );
166 sh->disp_w=width=cinfo.image_width;
167 sh->disp_h=height=cinfo.image_height;
168 jpeg_start_decompress( &cinfo );
169 depth=cinfo.output_components * 8;
171 switch( depth ) {
172 case 8:
173 case 24: break;
174 default: mp_msg( MSGT_DECVIDEO,MSGL_ERR,"Sorry, unsupported JPEG colorspace: %d.\n",depth ); return NULL;
177 if ( last_w!=width || last_h!=height || last_depth != depth )
179 last_depth = depth;
180 if(!mpcodecs_config_vo( sh,width,height, depth == 8 ? IMGFMT_Y8 : IMGFMT_RGB24 )) return NULL;
181 last_w=width; last_h=height;
184 mpi=mpcodecs_get_image( sh,MP_IMGTYPE_TEMP,MP_IMGFLAG_ACCEPT_STRIDE,width,height );
185 if ( !mpi ) return NULL;
187 for ( i=0;i < height;i++ )
189 unsigned char * drow = mpi->planes[0] + mpi->stride[0] * i;
190 jpeg_read_scanlines( &cinfo,(JSAMPLE**)&drow,1 );
193 jpeg_finish_decompress(&cinfo);
194 jpeg_destroy_decompress(&cinfo);
196 return mpi;