Mercurial > mplayer.hg
annotate libmpcodecs/vd_libmpeg2.c @ 23011:365eef1fc4f0
Disable caching of rotated glyphs.
The following commits will add perspective distortion to the glyphs rotated
with \frx and \fry. Somewhere along the way correct caching of such glyphs
will become impossible, but in the end everything will be fine.
author | eugeni |
---|---|
date | Fri, 20 Apr 2007 22:49:48 +0000 |
parents | 2a2f3db46103 |
children | b3726f27695f |
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 |
4998 | 6 #include "mp_msg.h" |
7 | |
8 #include "vd_internal.h" | |
9 | |
9859 | 10 //#undef MPEG12_POSTPROC |
11 | |
4998 | 12 static vd_info_t info = |
13 { | |
12932 | 14 "MPEG 1/2 Video decoder libmpeg2-v0.4.0b", |
4998 | 15 "libmpeg2", |
9859 | 16 "A'rpi & Fabian Franz", |
4998 | 17 "Aaron & Walken", |
18 "native" | |
19 }; | |
20 | |
21 LIBVD_EXTERN(libmpeg2) | |
22 | |
9859 | 23 //#include "libvo/video_out.h" // FIXME!!! |
5465 | 24 |
4998 | 25 #include "libmpeg2/mpeg2.h" |
12932 | 26 #include "libmpeg2/attributes.h" |
4998 | 27 #include "libmpeg2/mpeg2_internal.h" |
28 | |
17012 | 29 #include "cpudetect.h" |
5465 | 30 |
18301 | 31 typedef struct { |
32 mpeg2dec_t *mpeg2dec; | |
33 int quant_store_idx; | |
34 char *quant_store[3]; | |
35 } vd_libmpeg2_ctx_t; | |
36 | |
4998 | 37 // to set/get/query special features/parameters |
38 static int control(sh_video_t *sh,int cmd,void* arg,...){ | |
18301 | 39 vd_libmpeg2_ctx_t *context = sh->context; |
40 mpeg2dec_t * mpeg2dec = context->mpeg2dec; | |
14012 | 41 const mpeg2_info_t * info = mpeg2_info (mpeg2dec); |
13995 | 42 |
43 switch(cmd) { | |
44 case VDCTRL_QUERY_FORMAT: | |
14012 | 45 if (info->sequence->width >> 1 == info->sequence->chroma_width && |
46 info->sequence->height >> 1 == info->sequence->chroma_height && | |
47 (*((int*)arg)) == IMGFMT_YV12) | |
13995 | 48 return CONTROL_TRUE; |
14012 | 49 if (info->sequence->width >> 1 == info->sequence->chroma_width && |
50 info->sequence->height == info->sequence->chroma_height && | |
51 (*((int*)arg)) == IMGFMT_422P) | |
13995 | 52 return CONTROL_TRUE; |
53 return CONTROL_FALSE; | |
54 } | |
55 | |
4998 | 56 return CONTROL_UNKNOWN; |
57 } | |
58 | |
59 // init driver | |
60 static int init(sh_video_t *sh){ | |
18301 | 61 vd_libmpeg2_ctx_t *context; |
9859 | 62 mpeg2dec_t * mpeg2dec; |
13995 | 63 // const mpeg2_info_t * info; |
9859 | 64 int accel; |
5465 | 65 |
9859 | 66 accel = 0; |
67 if(gCpuCaps.hasMMX) | |
68 accel |= MPEG2_ACCEL_X86_MMX; | |
69 if(gCpuCaps.hasMMX2) | |
70 accel |= MPEG2_ACCEL_X86_MMXEXT; | |
71 if(gCpuCaps.has3DNow) | |
72 accel |= MPEG2_ACCEL_X86_3DNOW; | |
10267
d953763cc555
libmpeg2-altivec patch by Magnus Damm <damm@opensource.se>:
arpi
parents:
10250
diff
changeset
|
73 if(gCpuCaps.hasAltiVec) |
d953763cc555
libmpeg2-altivec patch by Magnus Damm <damm@opensource.se>:
arpi
parents:
10250
diff
changeset
|
74 accel |= MPEG2_ACCEL_PPC_ALTIVEC; |
13117 | 75 #ifdef HAVE_VIS |
76 accel |= MPEG2_ACCEL_SPARC_VIS; | |
9859 | 77 #endif |
78 mpeg2_accel(accel); | |
5465 | 79 |
9859 | 80 mpeg2dec = mpeg2_init (); |
81 | |
82 if(!mpeg2dec) return 0; | |
83 | |
84 mpeg2_custom_fbuf(mpeg2dec,1); // enable DR1 | |
18301 | 85 |
86 context = calloc(1, sizeof(vd_libmpeg2_ctx_t)); | |
87 context->mpeg2dec = mpeg2dec; | |
88 sh->context = context; | |
9859 | 89 |
13112 | 90 mpeg2dec->pending_buffer = 0; |
91 mpeg2dec->pending_length = 0; | |
92 | |
9859 | 93 return 1; |
4998 | 94 } |
95 | |
96 // uninit driver | |
97 static void uninit(sh_video_t *sh){ | |
18301 | 98 int i; |
99 vd_libmpeg2_ctx_t *context = sh->context; | |
100 mpeg2dec_t * mpeg2dec = context->mpeg2dec; | |
13112 | 101 if (mpeg2dec->pending_buffer) free(mpeg2dec->pending_buffer); |
14012 | 102 mpeg2dec->decoder.convert=NULL; |
103 mpeg2dec->decoder.convert_id=NULL; | |
9859 | 104 mpeg2_close (mpeg2dec); |
18301 | 105 for (i=0; i < 3; i++) |
106 free(context->quant_store[i]); | |
107 free(sh->context); | |
4998 | 108 } |
109 | |
13112 | 110 static void draw_slice (void * _sh, uint8_t * const * src, unsigned int y){ |
9859 | 111 sh_video_t* sh = (sh_video_t*) _sh; |
18301 | 112 vd_libmpeg2_ctx_t *context = sh->context; |
113 mpeg2dec_t* mpeg2dec = context->mpeg2dec; | |
9859 | 114 const mpeg2_info_t * info = mpeg2_info (mpeg2dec); |
115 int stride[3]; | |
5465 | 116 |
13112 | 117 // printf("draw_slice() y=%d \n",y); |
5465 | 118 |
9859 | 119 stride[0]=mpeg2dec->decoder.stride; |
120 stride[1]=stride[2]=mpeg2dec->decoder.uv_stride; | |
5465 | 121 |
9859 | 122 mpcodecs_draw_slice(sh, (uint8_t **)src, |
12572
7d681d8ebab8
display height may be a lot smaller or larger than picture height, sample provided by winnicki
iive
parents:
11080
diff
changeset
|
123 stride, info->sequence->picture_width, |
7d681d8ebab8
display height may be a lot smaller or larger than picture height, sample provided by winnicki
iive
parents:
11080
diff
changeset
|
124 (y+16<=info->sequence->picture_height) ? 16 : |
7d681d8ebab8
display height may be a lot smaller or larger than picture height, sample provided by winnicki
iive
parents:
11080
diff
changeset
|
125 info->sequence->picture_height-y, |
9859 | 126 0, y); |
4998 | 127 } |
128 | |
5465 | 129 // decode a frame |
130 static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ | |
18301 | 131 vd_libmpeg2_ctx_t *context = sh->context; |
132 mpeg2dec_t * mpeg2dec = context->mpeg2dec; | |
9859 | 133 const mpeg2_info_t * info = mpeg2_info (mpeg2dec); |
134 int drop_frame, framedrop=flags&3; | |
135 | |
13995 | 136 // MPlayer registers its own draw_slice callback, prevent libmpeg2 from freeing the context |
14012 | 137 mpeg2dec->decoder.convert=NULL; |
138 mpeg2dec->decoder.convert_id=NULL; | |
13150 | 139 |
11080
26f1b3ad4a77
skip null frames in mpeg files, patch by Zoltan Hidvegi <mplayer@hzoli.2y.net>
attila
parents:
10663
diff
changeset
|
140 if(len<=0) return NULL; // skipped null frame |
26f1b3ad4a77
skip null frames in mpeg files, patch by Zoltan Hidvegi <mplayer@hzoli.2y.net>
attila
parents:
10663
diff
changeset
|
141 |
9859 | 142 // append extra 'end of frame' code: |
143 ((char*)data+len)[0]=0; | |
144 ((char*)data+len)[1]=0; | |
145 ((char*)data+len)[2]=1; | |
146 ((char*)data+len)[3]=0xff; | |
147 len+=4; | |
5465 | 148 |
13112 | 149 if (mpeg2dec->pending_length) { |
150 mpeg2_buffer (mpeg2dec, mpeg2dec->pending_buffer, mpeg2dec->pending_buffer + mpeg2dec->pending_length); | |
151 } else { | |
152 mpeg2_buffer (mpeg2dec, data, data+len); | |
153 } | |
9859 | 154 |
155 while(1){ | |
156 int state=mpeg2_parse (mpeg2dec); | |
13995 | 157 int type, use_callback; |
158 mp_image_t* mpi_new; | |
18428
22805699b7b1
moved code to set aspect ratio for mpeg12 away from video.c and into decoder files; A/R changes work correctly with -vc mpeg12
nicodvb
parents:
18301
diff
changeset
|
159 unsigned long pw, ph; |
13995 | 160 |
9859 | 161 switch(state){ |
12932 | 162 case STATE_BUFFER: |
13112 | 163 if (mpeg2dec->pending_length) { |
13152 | 164 // just finished the pending data, continue with processing of the passed buffer |
13112 | 165 mpeg2dec->pending_length = 0; |
166 mpeg2_buffer (mpeg2dec, data, data+len); | |
167 } else { | |
168 // parsing of the passed buffer finished, return. | |
169 return 0; | |
170 } | |
171 break; | |
9859 | 172 case STATE_SEQUENCE: |
18428
22805699b7b1
moved code to set aspect ratio for mpeg12 away from video.c and into decoder files; A/R changes work correctly with -vc mpeg12
nicodvb
parents:
18301
diff
changeset
|
173 pw = info->sequence->display_width * info->sequence->pixel_width; |
22805699b7b1
moved code to set aspect ratio for mpeg12 away from video.c and into decoder files; A/R changes work correctly with -vc mpeg12
nicodvb
parents:
18301
diff
changeset
|
174 ph = info->sequence->display_height * info->sequence->pixel_height; |
22805699b7b1
moved code to set aspect ratio for mpeg12 away from video.c and into decoder files; A/R changes work correctly with -vc mpeg12
nicodvb
parents:
18301
diff
changeset
|
175 if(ph) sh->aspect = (float) pw / (float) ph; |
9859 | 176 // video parameters inited/changed, (re)init libvo: |
13995 | 177 if (info->sequence->width >> 1 == info->sequence->chroma_width && |
178 info->sequence->height >> 1 == info->sequence->chroma_height) { | |
179 if(!mpcodecs_config_vo(sh, | |
14016 | 180 info->sequence->picture_width, |
181 info->sequence->picture_height, IMGFMT_YV12)) return 0; | |
13995 | 182 } else if (info->sequence->width >> 1 == info->sequence->chroma_width && |
183 info->sequence->height == info->sequence->chroma_height) { | |
184 if(!mpcodecs_config_vo(sh, | |
14016 | 185 info->sequence->picture_width, |
186 info->sequence->picture_height, IMGFMT_422P)) return 0; | |
13995 | 187 } else return 0; |
9859 | 188 break; |
13995 | 189 case STATE_PICTURE: |
190 type=info->current_picture->flags&PIC_MASK_CODING_TYPE; | |
9859 | 191 |
192 drop_frame = framedrop && (mpeg2dec->decoder.coding_type == B_TYPE); | |
193 drop_frame |= framedrop>=2; // hard drop | |
194 if (drop_frame) { | |
195 mpeg2_skip(mpeg2dec, 1); | |
196 //printf("Dropping Frame ...\n"); | |
197 break; | |
198 } | |
199 mpeg2_skip(mpeg2dec, 0); //mpeg2skip skips frames until set again to 0 | |
200 | |
14012 | 201 use_callback = (!framedrop && vd_use_slices && |
202 (info->current_picture->flags&PIC_FLAG_PROGRESSIVE_FRAME)) ? | |
203 MP_IMGFLAG_DRAW_CALLBACK:0; | |
13995 | 204 |
9859 | 205 // get_buffer "callback": |
13995 | 206 mpi_new=mpcodecs_get_image(sh,MP_IMGTYPE_IPB, |
14012 | 207 (type==PIC_FLAG_CODING_TYPE_B) ? |
208 use_callback : (MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE), | |
14075 | 209 info->sequence->width, |
210 info->sequence->height); | |
13995 | 211 |
13112 | 212 if(!mpi_new) return 0; // VO ERROR!!!!!!!! |
213 mpeg2_set_buf(mpeg2dec, mpi_new->planes, mpi_new); | |
20591
ca1d5d9fe51c
Set mpi stride, mostly fixes http://samples.mplayerhq.hu/MPEG2/res_change_ffmpeg_aspect.ts
reimar
parents:
18771
diff
changeset
|
214 mpi_new->stride[0] = info->sequence->width; |
ca1d5d9fe51c
Set mpi stride, mostly fixes http://samples.mplayerhq.hu/MPEG2/res_change_ffmpeg_aspect.ts
reimar
parents:
18771
diff
changeset
|
215 mpi_new->stride[1] = info->sequence->chroma_width; |
ca1d5d9fe51c
Set mpi stride, mostly fixes http://samples.mplayerhq.hu/MPEG2/res_change_ffmpeg_aspect.ts
reimar
parents:
18771
diff
changeset
|
216 mpi_new->stride[2] = info->sequence->chroma_width; |
10510
73b3e4336cd4
Add mpeg2_flags to mp_image_t, copy flags in vd_libmpeg2.c,
ranma
parents:
10267
diff
changeset
|
217 if (info->current_picture->flags&PIC_FLAG_TOP_FIELD_FIRST) |
13112 | 218 mpi_new->fields |= MP_IMGFIELD_TOP_FIRST; |
219 else mpi_new->fields &= ~MP_IMGFIELD_TOP_FIRST; | |
10510
73b3e4336cd4
Add mpeg2_flags to mp_image_t, copy flags in vd_libmpeg2.c,
ranma
parents:
10267
diff
changeset
|
220 if (info->current_picture->flags&PIC_FLAG_REPEAT_FIRST_FIELD) |
13112 | 221 mpi_new->fields |= MP_IMGFIELD_REPEAT_FIRST; |
222 else mpi_new->fields &= ~MP_IMGFIELD_REPEAT_FIRST; | |
223 mpi_new->fields |= MP_IMGFIELD_ORDERED; | |
20639 | 224 if (!(info->current_picture->flags&PIC_FLAG_PROGRESSIVE_FRAME)) |
225 mpi_new->fields |= MP_IMGFIELD_INTERLACED; | |
9859 | 226 |
12935 | 227 #ifdef MPEG12_POSTPROC |
18301 | 228 mpi_new->qstride=info->sequence->width>>4; |
229 { | |
230 char **p = &context->quant_store[type==PIC_FLAG_CODING_TYPE_B ? | |
231 2 : (context->quant_store_idx ^= 1)]; | |
232 *p = realloc(*p, mpi_new->qstride*(info->sequence->height>>4)); | |
233 mpi_new->qscale = *p; | |
12935 | 234 } |
13112 | 235 mpeg2dec->decoder.quant_store=mpi_new->qscale; |
236 mpeg2dec->decoder.quant_stride=mpi_new->qstride; | |
237 mpi_new->pict_type=type; // 1->I, 2->P, 3->B | |
238 mpi_new->qscale_type= 1; | |
12935 | 239 #endif |
240 | |
14012 | 241 if (mpi_new->flags&MP_IMGFLAG_DRAW_CALLBACK |
242 && !(mpi_new->flags&MP_IMGFLAG_DIRECT)) { | |
243 // nice, filter/vo likes draw_callback :) | |
244 mpeg2dec->decoder.convert=draw_slice; | |
245 mpeg2dec->decoder.convert_id=sh; | |
246 } else { | |
247 mpeg2dec->decoder.convert=NULL; | |
248 mpeg2dec->decoder.convert_id=NULL; | |
13995 | 249 } |
250 | |
9859 | 251 break; |
252 case STATE_SLICE: | |
253 case STATE_END: | |
12932 | 254 case STATE_INVALID_END: |
9859 | 255 // decoding done: |
13112 | 256 if(info->display_fbuf) { |
13152 | 257 mp_image_t* mpi = info->display_fbuf->id; |
258 if (mpeg2dec->pending_length == 0) { | |
13995 | 259 mpeg2dec->pending_length = mpeg2dec->buf_end - mpeg2dec->buf_start; |
260 mpeg2dec->pending_buffer = realloc(mpeg2dec->pending_buffer, mpeg2dec->pending_length); | |
261 memcpy(mpeg2dec->pending_buffer, mpeg2dec->buf_start, mpeg2dec->pending_length); | |
13152 | 262 } else { |
263 // still some data in the pending buffer, shouldn't happen | |
264 mpeg2dec->pending_length = mpeg2dec->buf_end - mpeg2dec->buf_start; | |
265 memmove(mpeg2dec->pending_buffer, mpeg2dec->buf_start, mpeg2dec->pending_length); | |
266 mpeg2dec->pending_buffer = realloc(mpeg2dec->pending_buffer, mpeg2dec->pending_length + len); | |
267 memcpy(mpeg2dec->pending_buffer+mpeg2dec->pending_length, data, len); | |
268 mpeg2dec->pending_length += len; | |
269 } | |
270 // fprintf(stderr, "pending = %d\n", mpeg2dec->pending_length); | |
13112 | 271 return mpi; |
272 } | |
7957
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
273 } |
31fd09cc9ba2
passing picture_type (might be usefull for postprocessing)
michael
parents:
7756
diff
changeset
|
274 } |
5465 | 275 } |