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