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