Mercurial > mplayer.hg
annotate libmpeg2/decode.c @ 2977:28bcf0ca1448
ao_mpegpes isn't really optional
author | pl |
---|---|
date | Sun, 18 Nov 2001 18:58:03 +0000 |
parents | 8e3875816f6d |
children | 5da6e1b6c93e |
rev | line source |
---|---|
1 | 1 /* Copyright (C) Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - Nov 1999 */ |
2 /* Some cleanup & hacking by A'rpi/ESP-team - Oct 2000 */ | |
3 | |
4 /* mpeg2dec version: */ | |
5 #define PACKAGE "mpeg2dec" | |
36 | 6 #define VERSION "0.2.0-release" |
1 | 7 |
2775 | 8 #include "config.h" |
9 | |
1 | 10 #include <stdio.h> |
2775 | 11 #ifdef HAVE_MALLOC_H |
12 #include <malloc.h> | |
13 #endif | |
1 | 14 #include <stdlib.h> |
15 #include <unistd.h> | |
16 #include <fcntl.h> | |
17 #include <errno.h> | |
18 | |
111 | 19 #include <signal.h> |
20 #include <setjmp.h> | |
21 | |
22 | |
1 | 23 |
36 | 24 #include "video_out.h" |
25 #include <inttypes.h> | |
1 | 26 |
27 #include "mpeg2.h" | |
28 #include "mpeg2_internal.h" | |
29 | |
30 #include "../linux/shmem.h" | |
31 | |
32 //#include "motion_comp.h" | |
33 //#include "idct.h" | |
34 //#include "header.h" | |
35 //#include "slice.h" | |
36 //#include "stats.h" | |
37 | |
38 #include "attributes.h" | |
39 #ifdef __i386__ | |
40 #include "mmx.h" | |
41 #endif | |
42 | |
36 | 43 #include "mm_accel.h" |
44 | |
45 | |
1 | 46 //this is where we keep the state of the decoder |
47 //picture_t picture_data; | |
48 //picture_t *picture=&picture_data; | |
49 picture_t *picture=NULL; | |
50 | |
51 //global config struct | |
52 mpeg2_config_t config; | |
53 | |
54 // the maximum chunk size is determined by vbv_buffer_size which is 224K for | |
55 // MP@ML streams. (we make no pretenses ofdecoding anything more than that) | |
56 //static uint8_t chunk_buffer[224 * 1024 + 4]; | |
57 //static uint32_t shift = 0; | |
58 | |
967 | 59 //static int drop_flag = 0; |
1 | 60 static int drop_frame = 0; |
61 | |
41 | 62 #ifdef MPEG12_POSTPROC |
2187 | 63 #include "../postproc/postprocess.h" |
2722 | 64 int quant_store[MPEG2_MBR+1][MPEG2_MBC+1]; // [Review] |
36 | 65 #endif |
1 | 66 |
1636 | 67 static table_init_state=0; |
68 | |
1 | 69 void mpeg2_init (void) |
70 { | |
71 | |
499 | 72 printf (PACKAGE"-"VERSION" (C) 2000-2001 Aaron Holtzman & Michel Lespinasse\n"); |
1 | 73 config.flags = 0; |
74 #ifdef HAVE_MMX | |
75 config.flags |= MM_ACCEL_X86_MMX; | |
76 #endif | |
77 #ifdef HAVE_SSE | |
78 config.flags |= MM_ACCEL_X86_MMXEXT; | |
79 #endif | |
80 #ifdef HAVE_3DNOW | |
81 config.flags |= MM_ACCEL_X86_3DNOW; | |
82 #endif | |
83 #ifdef HAVE_MLIB | |
84 config.flags |= MM_ACCEL_MLIB; | |
85 #endif | |
86 | |
499 | 87 // printf("libmpeg2 config flags = 0x%X\n",config.flags); |
1 | 88 |
1652
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
89 picture=malloc(sizeof(picture_t)); // !!! NEW HACK :) !!! |
1655 | 90 memset(picture,0,sizeof(picture_t)); |
1 | 91 |
92 header_state_init (picture); | |
36 | 93 // picture->repeat_count=0; |
1 | 94 |
95 picture->pp_options=0; | |
96 | |
1636 | 97 if(!table_init_state){ |
98 idct_init (); | |
99 motion_comp_init (); | |
100 table_init_state=1; | |
101 } | |
1 | 102 } |
103 | |
41 | 104 static vo_frame_t frames[4]; |
36 | 105 |
1 | 106 void mpeg2_allocate_image_buffers (picture_t * picture) |
107 { | |
108 int frame_size,buff_size; | |
109 unsigned char *base=NULL; | |
36 | 110 int i; |
1 | 111 |
112 // height+1 requires for yuv2rgb_mmx code (it reads next line after last) | |
113 frame_size = picture->coded_picture_width * (1+picture->coded_picture_height); | |
114 frame_size = (frame_size+31)&(~31); // align to 32 byte boundary | |
115 buff_size = frame_size + (frame_size/4)*2; // 4Y + 1U + 1V | |
116 | |
117 // allocate images in YV12 format | |
41 | 118 #ifdef MPEG12_POSTPROC |
119 for(i=0;i<4;i++){ | |
120 #else | |
36 | 121 for(i=0;i<3;i++){ |
41 | 122 #endif |
2080 | 123 base = (unsigned char *)memalign(64,buff_size); |
36 | 124 frames[i].base[0] = base; |
125 frames[i].base[1] = base + frame_size * 5 / 4; | |
126 frames[i].base[2] = base + frame_size; | |
127 frames[i].copy = NULL; | |
128 frames[i].vo = NULL; | |
129 } | |
130 | |
131 picture->forward_reference_frame=&frames[0]; | |
132 picture->backward_reference_frame=&frames[1]; | |
133 picture->current_frame=&frames[2]; | |
1 | 134 |
135 } | |
136 | |
1652
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
137 void mpeg2_free_image_buffers (picture_t * picture){ |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
138 int i; |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
139 |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
140 #ifdef MPEG12_POSTPROC |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
141 for(i=0;i<4;i++){ |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
142 #else |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
143 for(i=0;i<3;i++){ |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
144 #endif |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
145 free(frames[i].base[0]); |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
146 } |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
147 |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
148 } |
e78cf3fc992e
shmem_alloc->memalign, adding function to free memory
arpi
parents:
1636
diff
changeset
|
149 |
36 | 150 static void copy_slice (vo_frame_t * frame, uint8_t ** src){ |
151 vo_functions_t * output = frame->vo; | |
152 int stride[3]; | |
79 | 153 int y=picture->slice<<4; |
154 uint8_t* src_tmp[3]; | |
1 | 155 |
36 | 156 stride[0]=picture->coded_picture_width; |
157 stride[1]=stride[2]=stride[0]/2; | |
79 | 158 |
159 if(frame!=picture->display_frame){ | |
160 uint8_t** base=picture->display_frame->base; | |
161 src_tmp[0]=base[0]+stride[0]*y; | |
162 src_tmp[1]=base[1]+stride[1]*(y>>1); | |
163 src_tmp[2]=base[2]+stride[2]*(y>>1); | |
164 src=src_tmp; | |
165 } | |
166 | |
167 output->draw_slice (src, | |
168 stride, picture->display_picture_width, | |
36 | 169 (y+16<=picture->display_picture_height) ? 16 : |
170 picture->display_picture_height-y, | |
171 0, y); | |
1 | 172 |
79 | 173 ++picture->slice; |
1 | 174 } |
2253 | 175 void draw_frame(vo_functions_t * output) |
176 { | |
177 int stride[3]; | |
178 | |
179 stride[0]=picture->coded_picture_width; | |
180 stride[1]=stride[2]=stride[0]/2; | |
181 #ifdef MPEG12_POSTPROC | |
182 if( picture->pp_options ) | |
183 {// apply postprocess filter | |
184 postprocess((picture->picture_coding_type == B_TYPE) ? | |
185 picture->current_frame->base : | |
186 picture->forward_reference_frame->base, | |
187 stride[0], frames[3].base, stride[0], | |
188 picture->coded_picture_width, picture->coded_picture_height, | |
2722 | 189 &quant_store[1][1], (MPEG2_MBC+1), picture->pp_options); |
2253 | 190 output->draw_slice (frames[3].base, stride, |
191 picture->display_picture_width, | |
192 picture->display_picture_height, 0, 0); | |
193 }else | |
194 #endif | |
195 { | |
196 output->draw_slice ((picture->picture_coding_type == B_TYPE) ? | |
197 picture->current_frame->base : | |
198 picture->forward_reference_frame->base, | |
199 stride, | |
200 picture->display_picture_width, | |
201 picture->display_picture_height, 0, 0); | |
202 } | |
203 } | |
1 | 204 |
205 static int in_slice_flag=0; | |
206 | |
967 | 207 static int parse_chunk (vo_functions_t * output, int code, uint8_t * buffer, int framedrop) |
1 | 208 { |
209 int is_frame_done = 0; | |
210 | |
211 stats_header (code, buffer); | |
212 | |
213 is_frame_done = in_slice_flag && ((!code) || (code >= 0xb0)); | |
214 if (is_frame_done) { | |
215 in_slice_flag = 0; | |
216 | |
36 | 217 // if(picture->picture_structure != FRAME_PICTURE) printf("Field! %d \n",picture->second_field); |
1 | 218 |
2019
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
219 if(picture->picture_structure == FRAME_PICTURE) |
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
220 { |
41 | 221 #ifdef MPEG12_POSTPROC |
2253 | 222 if( (picture->pp_options) && (!framedrop) ) |
223 draw_frame(output); | |
2019
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
224 #endif |
2253 | 225 }else |
226 { | |
227 if( (picture->second_field) && (!framedrop) ) | |
228 draw_frame(output); | |
229 else | |
230 is_frame_done=0;// we don't draw first fields | |
2019
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
231 } |
1 | 232 #ifdef ARCH_X86 |
36 | 233 if (config.flags & MM_ACCEL_X86_MMX) emms(); |
1 | 234 #endif |
116 | 235 // output->flip_page(); |
1 | 236 } |
237 | |
238 switch (code) { | |
239 case 0x00: /* picture_start_code */ | |
240 if (header_process_picture_header (picture, buffer)) { | |
241 printf ("bad picture header\n"); | |
114 | 242 //exit (1); |
1 | 243 } |
244 | |
967 | 245 drop_frame = framedrop && (picture->picture_coding_type == B_TYPE); |
246 drop_frame |= framedrop>=2; // hard drop | |
1 | 247 //decode_reorder_frames (); |
248 break; | |
249 | |
250 case 0xb3: /* sequence_header_code */ | |
251 if (header_process_sequence_header (picture, buffer)) { | |
252 printf ("bad sequence header\n"); | |
114 | 253 //exit (1); |
1 | 254 } |
255 break; | |
256 | |
257 case 0xb5: /* extension_start_code */ | |
258 if (header_process_extension (picture, buffer)) { | |
259 printf ("bad extension\n"); | |
114 | 260 //exit (1); |
1 | 261 } |
262 break; | |
263 | |
264 default: | |
265 // if (code >= 0xb9) printf ("stream not demultiplexed ?\n"); | |
266 if (code >= 0xb0) break; | |
267 | |
268 if (!(in_slice_flag)) { | |
269 in_slice_flag = 1; | |
270 | |
36 | 271 // if(!(picture->second_field)) decode_reorder_frames (); |
272 | |
273 // set current_frame pointer: | |
274 if (picture->second_field){ | |
275 // vo_field (picture->current_frame, picture->picture_structure); | |
276 } else { | |
277 if (picture->picture_coding_type == B_TYPE){ | |
79 | 278 picture->display_frame= |
36 | 279 picture->current_frame = &frames[2]; |
79 | 280 // picture->current_frame->copy=copy_slice; |
281 } else { | |
282 picture->current_frame = picture->forward_reference_frame; | |
283 picture->display_frame= | |
284 picture->forward_reference_frame = picture->backward_reference_frame; | |
285 picture->backward_reference_frame = picture->current_frame; | |
286 // picture->current_frame->copy=NULL; | |
287 } | |
288 } | |
289 | |
41 | 290 #ifdef MPEG12_POSTPROC |
2019
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
291 if(picture->pp_options) |
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
292 picture->current_frame->copy=NULL; |
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
293 else |
41 | 294 #endif |
2019
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
295 picture->current_frame->copy=copy_slice; |
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
296 |
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
297 |
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
298 if ((framedrop) || (picture->picture_structure != FRAME_PICTURE) ) |
7de4eceac32f
mpeg2-interlaced patch by Ivan Kalvatchev <iive@yahoo.com>
arpi
parents:
1655
diff
changeset
|
299 picture->current_frame->copy=NULL; |
36 | 300 picture->current_frame->vo=output; |
79 | 301 picture->slice=0; |
36 | 302 |
1 | 303 } |
304 | |
305 if (!drop_frame) { | |
306 | |
307 slice_process (picture, code, buffer); | |
308 | |
309 #ifdef ARCH_X86 | |
310 if (config.flags & MM_ACCEL_X86_MMX) emms (); | |
311 #endif | |
312 | |
313 } | |
314 } | |
315 | |
316 return is_frame_done; | |
317 } | |
318 | |
111 | 319 static jmp_buf mpeg2_jmp_buf; |
320 | |
321 static void mpeg2_sighandler(int sig){ | |
322 longjmp(mpeg2_jmp_buf,1); | |
323 } | |
1 | 324 |
967 | 325 int mpeg2_decode_data (vo_functions_t *output, uint8_t *current, uint8_t *end,int framedrop) |
1 | 326 { |
327 //static uint8_t code = 0xff; | |
328 //static uint8_t chunk_buffer[65536]; | |
329 //static uint8_t *chunk_ptr = chunk_buffer; | |
330 //static uint32_t shift = 0; | |
331 uint8_t code; | |
332 uint8_t *pos=NULL; | |
333 uint8_t *start=current; | |
334 int ret = 0; | |
111 | 335 void* old_sigh; |
336 | |
337 if(setjmp(mpeg2_jmp_buf)!=0){ | |
338 printf("@@@ FATAL!!!??? libmpeg2 returned from sig11 before the actual decoding! @@@\n"); | |
339 return 0; | |
340 } | |
341 | |
342 old_sigh=signal(SIGSEGV,mpeg2_sighandler); | |
1 | 343 |
344 // printf("RCVD %d bytes\n",end-current); | |
345 | |
346 while(current<end){ | |
347 // FIND NEXT HEAD: | |
348 unsigned int head=-1; | |
349 uint8_t c; | |
350 //-------------------- | |
351 while(current<end){ | |
352 c=current[0]; | |
353 ++current; | |
354 head<<=8; | |
355 if(head==0x100) break; // synced | |
356 head|=c; | |
357 } | |
358 //-------------------- | |
359 if(pos){ | |
360 //if((code&0x100)!=0x100) printf("libmpeg2: FATAL! code=%X\n",code); | |
361 //printf("pos=%d chunk %3X size=%d next-code=%X\n",pos-start,code,current-pos,head|c); | |
111 | 362 if(setjmp(mpeg2_jmp_buf)==0){ |
967 | 363 ret+=parse_chunk(output, code&0xFF, pos, framedrop); |
111 | 364 } else { |
204 | 365 #ifdef ARCH_X86 |
366 if (config.flags & MM_ACCEL_X86_MMX) emms (); | |
367 #endif | |
499 | 368 printf("@@@ libmpeg2 returned from sig11... (bad file?) @@@\n"); |
111 | 369 } |
1 | 370 } |
371 //-------------------- | |
372 pos=current;code=head|c; | |
373 } | |
374 | |
111 | 375 signal(SIGSEGV,old_sigh); // restore sighandler |
376 | |
967 | 377 if(code==0x1FF) ret+=parse_chunk(output, 0xFF, NULL, framedrop); // send 'end of frame' |
1 | 378 |
379 return ret; | |
380 } | |
381 | |
967 | 382 //void mpeg2_drop (int flag) |
383 //{ | |
384 // drop_flag = flag; | |
385 //} | |
1 | 386 |