Mercurial > mplayer.hg
annotate libmpcodecs/vd_libmpeg2.c @ 9554:12eae4cb4e56
new version of the de-telecine filter, largely rewritten. should work
much better. please report if there are any cases where the old one
worked better. the docs could also use some nicer formatting...
| author | rfelker |
|---|---|
| date | Sun, 09 Mar 2003 18:15:16 +0000 |
| parents | b465ba5897a3 |
| children | 16a7d1f4da38 |
| rev | line source |
|---|---|
| 4998 | 1 #include <stdio.h> |
| 2 #include <stdlib.h> | |
| 3 | |
| 4 #include "config.h" | |
|
8026
b465ba5897a3
usage of libmpeg2, liba52, mp3lib & svq1 can be disabled
arpi
parents:
7957
diff
changeset
|
5 #ifdef USE_LIBMPEG2 |
|
b465ba5897a3
usage of libmpeg2, liba52, mp3lib & svq1 can be disabled
arpi
parents:
7957
diff
changeset
|
6 |
| 4998 | 7 #include "mp_msg.h" |
| 8 | |
| 9 #include "vd_internal.h" | |
| 10 | |
| 11 static vd_info_t info = | |
| 12 { | |
| 5465 | 13 "MPEG 1/2 Video decoder v2.0", |
| 4998 | 14 "libmpeg2", |
| 15 "A'rpi", | |
| 16 "Aaron & Walken", | |
| 17 "native" | |
| 18 }; | |
| 19 | |
| 20 LIBVD_EXTERN(libmpeg2) | |
| 21 | |
| 5465 | 22 #define USE_SIGJMP_TRICK |
| 4998 | 23 |
| 5465 | 24 #ifdef USE_SIGJMP_TRICK |
| 25 #include <signal.h> | |
| 26 #include <setjmp.h> | |
| 27 #endif | |
| 28 | |
| 29 //#include "libmpdemux/parse_es.h" | |
| 30 | |
| 31 #include "libvo/video_out.h" // FIXME!!! | |
| 32 | |
| 4998 | 33 #include "libmpeg2/mpeg2.h" |
| 34 #include "libmpeg2/mpeg2_internal.h" | |
| 5465 | 35 #include "libmpeg2/mm_accel.h" |
| 4998 | 36 |
| 5465 | 37 #include "../cpudetect.h" |
| 38 | |
| 39 mpeg2_config_t config; // FIXME!!! | |
| 40 static picture_t *picture=NULL; // exported from libmpeg2/decode.c | |
| 41 | |
| 42 static int table_init_state=0; | |
| 43 | |
| 4998 | 44 // to set/get/query special features/parameters |
| 45 static int control(sh_video_t *sh,int cmd,void* arg,...){ | |
| 46 return CONTROL_UNKNOWN; | |
| 47 } | |
| 48 | |
| 5465 | 49 static vo_frame_t frames[3]; |
| 50 | |
| 4998 | 51 // init driver |
| 52 static int init(sh_video_t *sh){ | |
| 5465 | 53 |
| 54 config.flags = 0; | |
| 55 if(gCpuCaps.hasMMX) | |
| 56 config.flags |= MM_ACCEL_X86_MMX; | |
| 57 if(gCpuCaps.hasMMX2) | |
| 58 config.flags |= MM_ACCEL_X86_MMXEXT; | |
| 59 if(gCpuCaps.has3DNow) | |
| 60 config.flags |= MM_ACCEL_X86_3DNOW; | |
| 61 #ifdef HAVE_MLIB | |
| 62 config.flags |= MM_ACCEL_MLIB; | |
| 63 #endif | |
| 64 | |
| 65 picture=malloc(sizeof(picture_t)); // !!! NEW HACK :) !!! | |
| 66 memset(picture,0,sizeof(picture_t)); | |
| 67 header_state_init (picture); | |
| 68 | |
| 69 if(!table_init_state){ | |
| 70 idct_init (); | |
| 71 motion_comp_init (); | |
| 72 table_init_state=1; | |
| 73 } | |
| 74 | |
| 5003 | 75 picture->pp_options=divx_quality; |
| 5465 | 76 |
|
5675
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
77 memset(frames,0,3*sizeof(vo_frame_t)); |
|
0ff1b9ab7afc
slices+field pictures fixed, initial sig11 workaround
arpi
parents:
5613
diff
changeset
|
78 |
| 5465 | 79 picture->forward_reference_frame=&frames[0]; |
| 80 picture->backward_reference_frame=&frames[1]; | |
| 81 picture->temp_frame=&frames[2]; | |
| 82 picture->current_frame=NULL; | |
| 83 | |
| 4998 | 84 // send seq header to the decoder: *** HACK *** |
| 5465 | 85 // mpeg2_decode_data(NULL,videobuffer,videobuffer+videobuf_len,0); |
| 86 // mpeg2_allocate_image_buffers (picture); | |
| 5124 | 87 return mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YV12); |
| 4998 | 88 } |
| 89 | |
| 90 // uninit driver | |
| 91 static void uninit(sh_video_t *sh){ | |
| 5465 | 92 // mpeg2_free_image_buffers (picture); |
| 93 } | |
| 94 | |
| 95 static void draw_slice (vo_frame_t * frame, uint8_t ** src){ | |
| 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 | |
|
7756
77076fb29637
10l. use mpcodecs_draw_slice, instead of libvo directly
arpi
parents:
7464
diff
changeset
|
102 mpcodecs_draw_slice(frame->vo, src, |
| 5465 | 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 | |
|
7756
77076fb29637
10l. use mpcodecs_draw_slice, instead of libvo directly
arpi
parents:
7464
diff
changeset
|
209 picture->current_frame->vo=sh; |
| 5465 | 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 | |
| 7464 | 290 // if(code==0x1FF){ |
| 5465 | 291 ret=parse_chunk(sh, 0xFF, NULL, framedrop); // send 'end of frame' |
| 292 if(ret) mpi=ret; | |
| 7464 | 293 // } |
| 5465 | 294 |
|
7957
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
295 if(mpi){ |
|
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
296 static int last_non_b_type= 0; |
|
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
297 |
|
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
298 if(picture->picture_coding_type == B_TYPE) |
|
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
299 mpi->pict_type= B_TYPE; |
|
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
300 else{ |
|
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
301 mpi->pict_type= last_non_b_type; |
|
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
302 last_non_b_type= picture->picture_coding_type; |
|
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
303 } |
|
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
304 } |
|
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
305 |
| 5465 | 306 return mpi; |
| 307 } | |
|
8026
b465ba5897a3
usage of libmpeg2, liba52, mp3lib & svq1 can be disabled
arpi
parents:
7957
diff
changeset
|
308 #endif |
