Mercurial > mplayer.hg
annotate libmpcodecs/vd_libmpeg2.c @ 6608:da27a1bc1763
fixing memory overwrite bugs in the new converters
author | michael |
---|---|
date | Sat, 29 Jun 2002 21:43:28 +0000 |
parents | 0ff1b9ab7afc |
children | 28677d779205 |
rev | line source |
---|---|
4998 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
3 | |
4 #include "config.h" | |
5 #include "mp_msg.h" | |
6 | |
7 #include "vd_internal.h" | |
8 | |
9 static vd_info_t info = | |
10 { | |
5465 | 11 "MPEG 1/2 Video decoder v2.0", |
4998 | 12 "libmpeg2", |
13 VFM_MPEG, | |
14 "A'rpi", | |
15 "Aaron & Walken", | |
16 "native" | |
17 }; | |
18 | |
19 LIBVD_EXTERN(libmpeg2) | |
20 | |
5465 | 21 #define USE_SIGJMP_TRICK |
4998 | 22 |
5465 | 23 #ifdef USE_SIGJMP_TRICK |
24 #include <signal.h> | |
25 #include <setjmp.h> | |
26 #endif | |
27 | |
28 //#include "libmpdemux/parse_es.h" | |
29 | |
30 #include "libvo/video_out.h" // FIXME!!! | |
31 | |
4998 | 32 #include "libmpeg2/mpeg2.h" |
33 #include "libmpeg2/mpeg2_internal.h" | |
5465 | 34 #include "libmpeg2/mm_accel.h" |
4998 | 35 |
5465 | 36 #include "../cpudetect.h" |
37 | |
38 mpeg2_config_t config; // FIXME!!! | |
39 static picture_t *picture=NULL; // exported from libmpeg2/decode.c | |
40 | |
41 static int table_init_state=0; | |
42 | |
4998 | 43 // to set/get/query special features/parameters |
44 static int control(sh_video_t *sh,int cmd,void* arg,...){ | |
45 return CONTROL_UNKNOWN; | |
46 } | |
47 | |
5465 | 48 static vo_frame_t frames[3]; |
49 | |
4998 | 50 // init driver |
51 static int init(sh_video_t *sh){ | |
5465 | 52 |
53 config.flags = 0; | |
54 if(gCpuCaps.hasMMX) | |
55 config.flags |= MM_ACCEL_X86_MMX; | |
56 if(gCpuCaps.hasMMX2) | |
57 config.flags |= MM_ACCEL_X86_MMXEXT; | |
58 if(gCpuCaps.has3DNow) | |
59 config.flags |= MM_ACCEL_X86_3DNOW; | |
60 #ifdef HAVE_MLIB | |
61 config.flags |= MM_ACCEL_MLIB; | |
62 #endif | |
63 | |
64 picture=malloc(sizeof(picture_t)); // !!! NEW HACK :) !!! | |
65 memset(picture,0,sizeof(picture_t)); | |
66 header_state_init (picture); | |
67 | |
68 if(!table_init_state){ | |
69 idct_init (); | |
70 motion_comp_init (); | |
71 table_init_state=1; | |
72 } | |
73 | |
5003 | 74 picture->pp_options=divx_quality; |
5465 | 75 |
5675
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
76 memset(frames,0,3*sizeof(vo_frame_t)); |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
77 |
5465 | 78 picture->forward_reference_frame=&frames[0]; |
79 picture->backward_reference_frame=&frames[1]; | |
80 picture->temp_frame=&frames[2]; | |
81 picture->current_frame=NULL; | |
82 | |
4998 | 83 // send seq header to the decoder: *** HACK *** |
5465 | 84 // mpeg2_decode_data(NULL,videobuffer,videobuffer+videobuf_len,0); |
85 // mpeg2_allocate_image_buffers (picture); | |
5124 | 86 return mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YV12); |
4998 | 87 } |
88 | |
89 // uninit driver | |
90 static void uninit(sh_video_t *sh){ | |
5465 | 91 // mpeg2_free_image_buffers (picture); |
92 } | |
93 | |
94 static void draw_slice (vo_frame_t * frame, uint8_t ** src){ | |
95 vo_functions_t * output = frame->vo; | |
96 int stride[3]; | |
97 int y=picture->slice<<4; | |
98 | |
99 stride[0]=picture->coded_picture_width; | |
100 stride[1]=stride[2]=stride[0]/2; | |
101 | |
102 output->draw_slice (src, | |
103 stride, picture->display_picture_width, | |
104 (y+16<=picture->display_picture_height) ? 16 : | |
105 picture->display_picture_height-y, | |
106 0, y); | |
107 | |
108 ++picture->slice; | |
4998 | 109 } |
110 | |
5465 | 111 static int in_slice_flag=0; // FIXME! move to picture struct |
112 static int drop_frame=0; // FIXME! move to picture struct | |
113 | |
114 static mp_image_t* parse_chunk (sh_video_t* sh, int code, uint8_t * buffer, int framedrop){ | |
115 mp_image_t* mpi=NULL; | |
116 | |
117 // stats_header (code, buffer); | |
118 | |
119 if (in_slice_flag && ((!code) || (code >= 0xb0))) { | |
120 // ok, we've completed decoding a frame/field! | |
121 in_slice_flag = 0; | |
122 mpi=picture->display_frame->mpi; | |
123 if(picture->picture_structure!=FRAME_PICTURE && !picture->second_field) | |
124 mpi=NULL; // we don't draw first fields! | |
125 } | |
126 | |
127 switch (code) { | |
128 case 0x00: /* picture_start_code */ | |
129 if (header_process_picture_header (picture, buffer)) { | |
130 printf ("bad picture header\n"); | |
131 } | |
132 drop_frame = framedrop && (picture->picture_coding_type == B_TYPE); | |
133 drop_frame |= framedrop>=2; // hard drop | |
134 break; | |
135 | |
136 case 0xb3: /* sequence_header_code */ | |
137 if (header_process_sequence_header (picture, buffer)) { | |
138 printf ("bad sequence header\n"); | |
139 } | |
140 break; | |
141 | |
142 case 0xb5: /* extension_start_code */ | |
143 if (header_process_extension (picture, buffer)) { | |
144 printf ("bad extension\n"); | |
145 } | |
146 break; | |
147 | |
148 default: | |
149 if (code >= 0xb0) break; | |
150 | |
151 if (!in_slice_flag) { | |
152 in_slice_flag = 1; | |
153 | |
154 // set current_frame pointer: | |
155 if (!picture->second_field){ | |
156 mp_image_t* mpi; | |
157 int flags; | |
158 if (picture->picture_coding_type == B_TYPE){ | |
5675
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
159 flags=(!framedrop && vd_use_slices && |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
160 picture->picture_structure==FRAME_PICTURE) ? |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
161 MP_IMGFLAG_DRAW_CALLBACK:0; |
5465 | 162 picture->display_frame= |
163 picture->current_frame = picture->temp_frame; | |
164 } else { | |
165 flags=MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE; | |
166 picture->current_frame = picture->forward_reference_frame; | |
167 picture->display_frame= | |
168 picture->forward_reference_frame = picture->backward_reference_frame; | |
169 picture->backward_reference_frame = picture->current_frame; | |
170 } | |
171 mpi=mpcodecs_get_image(sh,MP_IMGTYPE_IPB, flags, | |
172 picture->coded_picture_width, | |
173 picture->coded_picture_height); | |
174 // ok, lets see what did we get: | |
175 if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK && | |
176 !(mpi->flags&MP_IMGFLAG_DIRECT)){ | |
177 // nice, filter/vo likes draw_callback :) | |
178 picture->current_frame->copy=draw_slice; | |
179 } else | |
180 picture->current_frame->copy=NULL; | |
181 // let's, setup pointers! | |
182 picture->current_frame->base[0]=mpi->planes[0]; | |
183 picture->current_frame->base[1]=mpi->planes[1]; | |
184 picture->current_frame->base[2]=mpi->planes[2]; | |
185 picture->current_frame->mpi=mpi; // tricky! | |
5675
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
186 #if 1 |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
187 if(!picture->forward_reference_frame->base[0]){ |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
188 // workaround for sig11 |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
189 picture->forward_reference_frame->base[0]=mpi->planes[0]; |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
190 picture->forward_reference_frame->base[1]=mpi->planes[1]; |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
191 picture->forward_reference_frame->base[2]=mpi->planes[2]; |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
192 } |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
193 if(!picture->backward_reference_frame->base[0]){ |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
194 // workaround for sig11 |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
195 picture->backward_reference_frame->base[0]=mpi->planes[0]; |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
196 picture->backward_reference_frame->base[1]=mpi->planes[1]; |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
197 picture->backward_reference_frame->base[2]=mpi->planes[2]; |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
198 } |
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
199 #endif |
5516 | 200 #ifdef MPEG12_POSTPROC |
5515 | 201 mpi->qscale=&picture->current_frame->quant_store[1][1]; |
202 mpi->qstride=(MPEG2_MBC+1); | |
5516 | 203 #endif |
5465 | 204 mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"mpeg2: [%c] %p %s \n", |
205 (picture->picture_coding_type == B_TYPE) ? 'B':'P', | |
206 mpi, (mpi->flags&MP_IMGFLAG_DIRECT)?"DR!":""); | |
207 } | |
208 | |
209 picture->current_frame->vo=sh->video_out; | |
210 picture->slice=0; | |
211 | |
212 } | |
213 | |
214 if (!drop_frame) { | |
215 slice_process (picture, code, buffer); | |
216 #ifdef ARCH_X86 | |
217 if (config.flags & MM_ACCEL_X86_MMX) __asm__ __volatile__ ("emms"); | |
218 #endif | |
219 } | |
220 | |
5145 | 221 } |
4998 | 222 return mpi; |
223 } | |
224 | |
5465 | 225 #ifdef USE_SIGJMP_TRICK |
226 | |
227 static jmp_buf mpeg2_jmp_buf; | |
228 | |
229 static void mpeg2_sighandler(int sig){ | |
230 longjmp(mpeg2_jmp_buf,1); | |
231 } | |
232 #endif | |
233 | |
234 // decode a frame | |
235 static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ | |
236 static uint32_t code; | |
237 static uint8_t* pos; | |
238 static uint8_t* current; | |
239 uint8_t* end=data+len; | |
240 static mp_image_t* mpi; | |
241 mp_image_t* ret=NULL; | |
242 int framedrop=flags&3; | |
243 void* old_sigh; | |
244 | |
245 // Note: static is REQUIRED because of longjmp() may destroy stack! | |
246 pos=NULL; | |
247 current=data; | |
248 mpi=NULL; | |
249 | |
250 #ifdef USE_SIGJMP_TRICK | |
251 old_sigh=signal(SIGSEGV,mpeg2_sighandler); | |
252 #endif | |
253 | |
254 while(current<end){ | |
255 // FIND NEXT HEAD: | |
256 static unsigned int head; | |
257 static uint8_t c; | |
258 head=-1; | |
259 //-------------------- | |
260 while(current<end){ | |
261 c=current[0]; | |
262 ++current; | |
263 head<<=8; | |
264 if(head==0x100) break; // synced | |
265 head|=c; | |
266 } | |
267 //-------------------- | |
268 if(pos){ | |
269 #ifdef USE_SIGJMP_TRICK | |
270 if(setjmp(mpeg2_jmp_buf)){ | |
271 #ifdef ARCH_X86 | |
272 if (config.flags & MM_ACCEL_X86_MMX) __asm__ __volatile__ ("emms"); | |
273 #endif | |
274 printf("@@@ libmpeg2 returned from sig11... (bad file?) @@@\n"); | |
275 } else | |
276 #endif | |
277 { | |
278 ret=parse_chunk(sh, code&0xFF, pos, framedrop); | |
279 if(ret) mpi=ret; | |
280 } | |
281 } | |
282 //-------------------- | |
283 pos=current;code=head|c; | |
284 } | |
285 | |
286 #ifdef USE_SIGJMP_TRICK | |
287 signal(SIGSEGV,old_sigh); // restore sighandler | |
288 #endif | |
289 | |
290 if(code==0x1FF){ | |
291 ret=parse_chunk(sh, 0xFF, NULL, framedrop); // send 'end of frame' | |
292 if(ret) mpi=ret; | |
293 } | |
294 | |
295 return mpi; | |
296 } |