Mercurial > libavcodec.hg
annotate mpegvideo_common.h @ 6017:e1404acccac3 libavcodec
Actually return with an error condition if we're being asked to deal with too
many reference frames. Also check max num ref frames against our internal
ref buffer sizes.
Part of fix for roundup issue 281
author | heydowns |
---|---|
date | Fri, 14 Dec 2007 05:48:27 +0000 |
parents | 1d83e9c34641 |
children | 493dc59d469a |
rev | line source |
---|---|
5204 | 1 /* |
2 * The simplest mpeg encoder (well, it was the simplest!) | |
3 * Copyright (c) 2000,2001 Fabrice Bellard. | |
4 * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> | |
5 * | |
5214 | 6 * 4MV & hq & B-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at> |
7 * | |
5204 | 8 * This file is part of FFmpeg. |
9 * | |
10 * FFmpeg is free software; you can redistribute it and/or | |
11 * modify it under the terms of the GNU Lesser General Public | |
12 * License as published by the Free Software Foundation; either | |
13 * version 2.1 of the License, or (at your option) any later version. | |
14 * | |
15 * FFmpeg is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 * Lesser General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU Lesser General Public | |
21 * License along with FFmpeg; if not, write to the Free Software | |
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
23 */ | |
24 | |
25 /** | |
26 * @file mpegvideo_common.h | |
27 * The simplest mpeg encoder (well, it was the simplest!). | |
28 */ | |
29 | |
5830
1d83e9c34641
Add FFMPEG_ prefix to all multiple inclusion guards.
diego
parents:
5433
diff
changeset
|
30 #ifndef FFMPEG_MPEGVIDEO_COMMON_H |
1d83e9c34641
Add FFMPEG_ prefix to all multiple inclusion guards.
diego
parents:
5433
diff
changeset
|
31 #define FFMPEG_MPEGVIDEO_COMMON_H |
5204 | 32 |
33 #include "avcodec.h" | |
34 #include "dsputil.h" | |
35 #include "mpegvideo.h" | |
36 #include "mjpegenc.h" | |
37 #include "msmpeg4.h" | |
38 #include "faandct.h" | |
39 #include <limits.h> | |
40 | |
41 int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow); | |
42 int dct_quantize_trellis_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow); | |
43 void denoise_dct_c(MpegEncContext *s, DCTELEM *block); | |
44 void copy_picture(Picture *dst, Picture *src); | |
45 | |
46 /** | |
47 * allocates a Picture | |
48 * The pixels are allocated/set by calling get_buffer() if shared=0 | |
49 */ | |
50 int alloc_picture(MpegEncContext *s, Picture *pic, int shared); | |
51 | |
52 /** | |
53 * sets the given MpegEncContext to common defaults (same for encoding and decoding). | |
54 * the changed fields will not depend upon the prior state of the MpegEncContext. | |
55 */ | |
56 void MPV_common_defaults(MpegEncContext *s); | |
57 | |
58 static inline void gmc1_motion(MpegEncContext *s, | |
59 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, | |
60 uint8_t **ref_picture) | |
61 { | |
62 uint8_t *ptr; | |
63 int offset, src_x, src_y, linesize, uvlinesize; | |
64 int motion_x, motion_y; | |
65 int emu=0; | |
66 | |
67 motion_x= s->sprite_offset[0][0]; | |
68 motion_y= s->sprite_offset[0][1]; | |
69 src_x = s->mb_x * 16 + (motion_x >> (s->sprite_warping_accuracy+1)); | |
70 src_y = s->mb_y * 16 + (motion_y >> (s->sprite_warping_accuracy+1)); | |
71 motion_x<<=(3-s->sprite_warping_accuracy); | |
72 motion_y<<=(3-s->sprite_warping_accuracy); | |
73 src_x = av_clip(src_x, -16, s->width); | |
74 if (src_x == s->width) | |
75 motion_x =0; | |
76 src_y = av_clip(src_y, -16, s->height); | |
77 if (src_y == s->height) | |
78 motion_y =0; | |
79 | |
80 linesize = s->linesize; | |
81 uvlinesize = s->uvlinesize; | |
82 | |
83 ptr = ref_picture[0] + (src_y * linesize) + src_x; | |
84 | |
85 if(s->flags&CODEC_FLAG_EMU_EDGE){ | |
86 if( (unsigned)src_x >= s->h_edge_pos - 17 | |
87 || (unsigned)src_y >= s->v_edge_pos - 17){ | |
88 ff_emulated_edge_mc(s->edge_emu_buffer, ptr, linesize, 17, 17, src_x, src_y, s->h_edge_pos, s->v_edge_pos); | |
89 ptr= s->edge_emu_buffer; | |
90 } | |
91 } | |
92 | |
93 if((motion_x|motion_y)&7){ | |
94 s->dsp.gmc1(dest_y , ptr , linesize, 16, motion_x&15, motion_y&15, 128 - s->no_rounding); | |
95 s->dsp.gmc1(dest_y+8, ptr+8, linesize, 16, motion_x&15, motion_y&15, 128 - s->no_rounding); | |
96 }else{ | |
97 int dxy; | |
98 | |
99 dxy= ((motion_x>>3)&1) | ((motion_y>>2)&2); | |
100 if (s->no_rounding){ | |
101 s->dsp.put_no_rnd_pixels_tab[0][dxy](dest_y, ptr, linesize, 16); | |
102 }else{ | |
103 s->dsp.put_pixels_tab [0][dxy](dest_y, ptr, linesize, 16); | |
104 } | |
105 } | |
106 | |
5433
ce0db8111f94
make grayscale only decoding checks in inner loops compiletime killable
michael
parents:
5428
diff
changeset
|
107 if(ENABLE_GRAY && s->flags&CODEC_FLAG_GRAY) return; |
5204 | 108 |
109 motion_x= s->sprite_offset[1][0]; | |
110 motion_y= s->sprite_offset[1][1]; | |
111 src_x = s->mb_x * 8 + (motion_x >> (s->sprite_warping_accuracy+1)); | |
112 src_y = s->mb_y * 8 + (motion_y >> (s->sprite_warping_accuracy+1)); | |
113 motion_x<<=(3-s->sprite_warping_accuracy); | |
114 motion_y<<=(3-s->sprite_warping_accuracy); | |
115 src_x = av_clip(src_x, -8, s->width>>1); | |
116 if (src_x == s->width>>1) | |
117 motion_x =0; | |
118 src_y = av_clip(src_y, -8, s->height>>1); | |
119 if (src_y == s->height>>1) | |
120 motion_y =0; | |
121 | |
122 offset = (src_y * uvlinesize) + src_x; | |
123 ptr = ref_picture[1] + offset; | |
124 if(s->flags&CODEC_FLAG_EMU_EDGE){ | |
125 if( (unsigned)src_x >= (s->h_edge_pos>>1) - 9 | |
126 || (unsigned)src_y >= (s->v_edge_pos>>1) - 9){ | |
127 ff_emulated_edge_mc(s->edge_emu_buffer, ptr, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); | |
128 ptr= s->edge_emu_buffer; | |
129 emu=1; | |
130 } | |
131 } | |
132 s->dsp.gmc1(dest_cb, ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding); | |
133 | |
134 ptr = ref_picture[2] + offset; | |
135 if(emu){ | |
136 ff_emulated_edge_mc(s->edge_emu_buffer, ptr, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); | |
137 ptr= s->edge_emu_buffer; | |
138 } | |
139 s->dsp.gmc1(dest_cr, ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding); | |
140 | |
141 return; | |
142 } | |
143 | |
144 static inline void gmc_motion(MpegEncContext *s, | |
145 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, | |
146 uint8_t **ref_picture) | |
147 { | |
148 uint8_t *ptr; | |
149 int linesize, uvlinesize; | |
150 const int a= s->sprite_warping_accuracy; | |
151 int ox, oy; | |
152 | |
153 linesize = s->linesize; | |
154 uvlinesize = s->uvlinesize; | |
155 | |
156 ptr = ref_picture[0]; | |
157 | |
158 ox= s->sprite_offset[0][0] + s->sprite_delta[0][0]*s->mb_x*16 + s->sprite_delta[0][1]*s->mb_y*16; | |
159 oy= s->sprite_offset[0][1] + s->sprite_delta[1][0]*s->mb_x*16 + s->sprite_delta[1][1]*s->mb_y*16; | |
160 | |
161 s->dsp.gmc(dest_y, ptr, linesize, 16, | |
162 ox, | |
163 oy, | |
164 s->sprite_delta[0][0], s->sprite_delta[0][1], | |
165 s->sprite_delta[1][0], s->sprite_delta[1][1], | |
166 a+1, (1<<(2*a+1)) - s->no_rounding, | |
167 s->h_edge_pos, s->v_edge_pos); | |
168 s->dsp.gmc(dest_y+8, ptr, linesize, 16, | |
169 ox + s->sprite_delta[0][0]*8, | |
170 oy + s->sprite_delta[1][0]*8, | |
171 s->sprite_delta[0][0], s->sprite_delta[0][1], | |
172 s->sprite_delta[1][0], s->sprite_delta[1][1], | |
173 a+1, (1<<(2*a+1)) - s->no_rounding, | |
174 s->h_edge_pos, s->v_edge_pos); | |
175 | |
5433
ce0db8111f94
make grayscale only decoding checks in inner loops compiletime killable
michael
parents:
5428
diff
changeset
|
176 if(ENABLE_GRAY && s->flags&CODEC_FLAG_GRAY) return; |
5204 | 177 |
178 ox= s->sprite_offset[1][0] + s->sprite_delta[0][0]*s->mb_x*8 + s->sprite_delta[0][1]*s->mb_y*8; | |
179 oy= s->sprite_offset[1][1] + s->sprite_delta[1][0]*s->mb_x*8 + s->sprite_delta[1][1]*s->mb_y*8; | |
180 | |
181 ptr = ref_picture[1]; | |
182 s->dsp.gmc(dest_cb, ptr, uvlinesize, 8, | |
183 ox, | |
184 oy, | |
185 s->sprite_delta[0][0], s->sprite_delta[0][1], | |
186 s->sprite_delta[1][0], s->sprite_delta[1][1], | |
187 a+1, (1<<(2*a+1)) - s->no_rounding, | |
188 s->h_edge_pos>>1, s->v_edge_pos>>1); | |
189 | |
190 ptr = ref_picture[2]; | |
191 s->dsp.gmc(dest_cr, ptr, uvlinesize, 8, | |
192 ox, | |
193 oy, | |
194 s->sprite_delta[0][0], s->sprite_delta[0][1], | |
195 s->sprite_delta[1][0], s->sprite_delta[1][1], | |
196 a+1, (1<<(2*a+1)) - s->no_rounding, | |
197 s->h_edge_pos>>1, s->v_edge_pos>>1); | |
198 } | |
199 | |
200 static inline int hpel_motion(MpegEncContext *s, | |
201 uint8_t *dest, uint8_t *src, | |
202 int field_based, int field_select, | |
203 int src_x, int src_y, | |
204 int width, int height, int stride, | |
205 int h_edge_pos, int v_edge_pos, | |
206 int w, int h, op_pixels_func *pix_op, | |
207 int motion_x, int motion_y) | |
208 { | |
209 int dxy; | |
210 int emu=0; | |
211 | |
212 dxy = ((motion_y & 1) << 1) | (motion_x & 1); | |
213 src_x += motion_x >> 1; | |
214 src_y += motion_y >> 1; | |
215 | |
216 /* WARNING: do no forget half pels */ | |
217 src_x = av_clip(src_x, -16, width); //FIXME unneeded for emu? | |
218 if (src_x == width) | |
219 dxy &= ~1; | |
220 src_y = av_clip(src_y, -16, height); | |
221 if (src_y == height) | |
222 dxy &= ~2; | |
223 src += src_y * stride + src_x; | |
224 | |
225 if(s->unrestricted_mv && (s->flags&CODEC_FLAG_EMU_EDGE)){ | |
226 if( (unsigned)src_x > h_edge_pos - (motion_x&1) - w | |
227 || (unsigned)src_y > v_edge_pos - (motion_y&1) - h){ | |
228 ff_emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w+1, (h+1)<<field_based, | |
229 src_x, src_y<<field_based, h_edge_pos, s->v_edge_pos); | |
230 src= s->edge_emu_buffer; | |
231 emu=1; | |
232 } | |
233 } | |
234 if(field_select) | |
235 src += s->linesize; | |
236 pix_op[dxy](dest, src, stride, h); | |
237 return emu; | |
238 } | |
239 | |
240 /* apply one mpeg motion vector to the three components */ | |
241 static av_always_inline void mpeg_motion(MpegEncContext *s, | |
242 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, | |
243 int field_based, int bottom_field, int field_select, | |
244 uint8_t **ref_picture, op_pixels_func (*pix_op)[4], | |
245 int motion_x, int motion_y, int h) | |
246 { | |
247 uint8_t *ptr_y, *ptr_cb, *ptr_cr; | |
248 int dxy, uvdxy, mx, my, src_x, src_y, uvsrc_x, uvsrc_y, v_edge_pos, uvlinesize, linesize; | |
249 | |
250 #if 0 | |
251 if(s->quarter_sample) | |
252 { | |
253 motion_x>>=1; | |
254 motion_y>>=1; | |
255 } | |
256 #endif | |
257 | |
258 v_edge_pos = s->v_edge_pos >> field_based; | |
259 linesize = s->current_picture.linesize[0] << field_based; | |
260 uvlinesize = s->current_picture.linesize[1] << field_based; | |
261 | |
262 dxy = ((motion_y & 1) << 1) | (motion_x & 1); | |
263 src_x = s->mb_x* 16 + (motion_x >> 1); | |
264 src_y =(s->mb_y<<(4-field_based)) + (motion_y >> 1); | |
265 | |
266 if (s->out_format == FMT_H263) { | |
267 if((s->workaround_bugs & FF_BUG_HPEL_CHROMA) && field_based){ | |
268 mx = (motion_x>>1)|(motion_x&1); | |
269 my = motion_y >>1; | |
270 uvdxy = ((my & 1) << 1) | (mx & 1); | |
271 uvsrc_x = s->mb_x* 8 + (mx >> 1); | |
272 uvsrc_y = (s->mb_y<<(3-field_based)) + (my >> 1); | |
273 }else{ | |
274 uvdxy = dxy | (motion_y & 2) | ((motion_x & 2) >> 1); | |
275 uvsrc_x = src_x>>1; | |
276 uvsrc_y = src_y>>1; | |
277 } | |
278 }else if(s->out_format == FMT_H261){//even chroma mv's are full pel in H261 | |
279 mx = motion_x / 4; | |
280 my = motion_y / 4; | |
281 uvdxy = 0; | |
282 uvsrc_x = s->mb_x*8 + mx; | |
283 uvsrc_y = s->mb_y*8 + my; | |
284 } else { | |
285 if(s->chroma_y_shift){ | |
286 mx = motion_x / 2; | |
287 my = motion_y / 2; | |
288 uvdxy = ((my & 1) << 1) | (mx & 1); | |
289 uvsrc_x = s->mb_x* 8 + (mx >> 1); | |
290 uvsrc_y = (s->mb_y<<(3-field_based)) + (my >> 1); | |
291 } else { | |
292 if(s->chroma_x_shift){ | |
293 //Chroma422 | |
294 mx = motion_x / 2; | |
295 uvdxy = ((motion_y & 1) << 1) | (mx & 1); | |
296 uvsrc_x = s->mb_x* 8 + (mx >> 1); | |
297 uvsrc_y = src_y; | |
298 } else { | |
299 //Chroma444 | |
300 uvdxy = dxy; | |
301 uvsrc_x = src_x; | |
302 uvsrc_y = src_y; | |
303 } | |
304 } | |
305 } | |
306 | |
307 ptr_y = ref_picture[0] + src_y * linesize + src_x; | |
308 ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; | |
309 ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; | |
310 | |
311 if( (unsigned)src_x > s->h_edge_pos - (motion_x&1) - 16 | |
312 || (unsigned)src_y > v_edge_pos - (motion_y&1) - h){ | |
313 if(s->codec_id == CODEC_ID_MPEG2VIDEO || | |
314 s->codec_id == CODEC_ID_MPEG1VIDEO){ | |
315 av_log(s->avctx,AV_LOG_DEBUG,"MPEG motion vector out of boundary\n"); | |
316 return ; | |
317 } | |
318 ff_emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based, | |
319 src_x, src_y<<field_based, s->h_edge_pos, s->v_edge_pos); | |
320 ptr_y = s->edge_emu_buffer; | |
5433
ce0db8111f94
make grayscale only decoding checks in inner loops compiletime killable
michael
parents:
5428
diff
changeset
|
321 if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ |
5204 | 322 uint8_t *uvbuf= s->edge_emu_buffer+18*s->linesize; |
323 ff_emulated_edge_mc(uvbuf , ptr_cb, s->uvlinesize, 9, 9+field_based, | |
324 uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); | |
325 ff_emulated_edge_mc(uvbuf+16, ptr_cr, s->uvlinesize, 9, 9+field_based, | |
326 uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); | |
327 ptr_cb= uvbuf; | |
328 ptr_cr= uvbuf+16; | |
329 } | |
330 } | |
331 | |
332 if(bottom_field){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.data | |
333 dest_y += s->linesize; | |
334 dest_cb+= s->uvlinesize; | |
335 dest_cr+= s->uvlinesize; | |
336 } | |
337 | |
338 if(field_select){ | |
339 ptr_y += s->linesize; | |
340 ptr_cb+= s->uvlinesize; | |
341 ptr_cr+= s->uvlinesize; | |
342 } | |
343 | |
344 pix_op[0][dxy](dest_y, ptr_y, linesize, h); | |
345 | |
5433
ce0db8111f94
make grayscale only decoding checks in inner loops compiletime killable
michael
parents:
5428
diff
changeset
|
346 if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ |
5204 | 347 pix_op[s->chroma_x_shift][uvdxy](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift); |
348 pix_op[s->chroma_x_shift][uvdxy](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift); | |
349 } | |
350 if((ENABLE_H261_ENCODER || ENABLE_H261_DECODER) && s->out_format == FMT_H261){ | |
351 ff_h261_loop_filter(s); | |
352 } | |
353 } | |
354 | |
355 //FIXME move to dsputil, avg variant, 16x16 version | |
356 static inline void put_obmc(uint8_t *dst, uint8_t *src[5], int stride){ | |
357 int x; | |
358 uint8_t * const top = src[1]; | |
359 uint8_t * const left = src[2]; | |
360 uint8_t * const mid = src[0]; | |
361 uint8_t * const right = src[3]; | |
362 uint8_t * const bottom= src[4]; | |
363 #define OBMC_FILTER(x, t, l, m, r, b)\ | |
364 dst[x]= (t*top[x] + l*left[x] + m*mid[x] + r*right[x] + b*bottom[x] + 4)>>3 | |
365 #define OBMC_FILTER4(x, t, l, m, r, b)\ | |
366 OBMC_FILTER(x , t, l, m, r, b);\ | |
367 OBMC_FILTER(x+1 , t, l, m, r, b);\ | |
368 OBMC_FILTER(x +stride, t, l, m, r, b);\ | |
369 OBMC_FILTER(x+1+stride, t, l, m, r, b); | |
370 | |
371 x=0; | |
372 OBMC_FILTER (x , 2, 2, 4, 0, 0); | |
373 OBMC_FILTER (x+1, 2, 1, 5, 0, 0); | |
374 OBMC_FILTER4(x+2, 2, 1, 5, 0, 0); | |
375 OBMC_FILTER4(x+4, 2, 0, 5, 1, 0); | |
376 OBMC_FILTER (x+6, 2, 0, 5, 1, 0); | |
377 OBMC_FILTER (x+7, 2, 0, 4, 2, 0); | |
378 x+= stride; | |
379 OBMC_FILTER (x , 1, 2, 5, 0, 0); | |
380 OBMC_FILTER (x+1, 1, 2, 5, 0, 0); | |
381 OBMC_FILTER (x+6, 1, 0, 5, 2, 0); | |
382 OBMC_FILTER (x+7, 1, 0, 5, 2, 0); | |
383 x+= stride; | |
384 OBMC_FILTER4(x , 1, 2, 5, 0, 0); | |
385 OBMC_FILTER4(x+2, 1, 1, 6, 0, 0); | |
386 OBMC_FILTER4(x+4, 1, 0, 6, 1, 0); | |
387 OBMC_FILTER4(x+6, 1, 0, 5, 2, 0); | |
388 x+= 2*stride; | |
389 OBMC_FILTER4(x , 0, 2, 5, 0, 1); | |
390 OBMC_FILTER4(x+2, 0, 1, 6, 0, 1); | |
391 OBMC_FILTER4(x+4, 0, 0, 6, 1, 1); | |
392 OBMC_FILTER4(x+6, 0, 0, 5, 2, 1); | |
393 x+= 2*stride; | |
394 OBMC_FILTER (x , 0, 2, 5, 0, 1); | |
395 OBMC_FILTER (x+1, 0, 2, 5, 0, 1); | |
396 OBMC_FILTER4(x+2, 0, 1, 5, 0, 2); | |
397 OBMC_FILTER4(x+4, 0, 0, 5, 1, 2); | |
398 OBMC_FILTER (x+6, 0, 0, 5, 2, 1); | |
399 OBMC_FILTER (x+7, 0, 0, 5, 2, 1); | |
400 x+= stride; | |
401 OBMC_FILTER (x , 0, 2, 4, 0, 2); | |
402 OBMC_FILTER (x+1, 0, 1, 5, 0, 2); | |
403 OBMC_FILTER (x+6, 0, 0, 5, 1, 2); | |
404 OBMC_FILTER (x+7, 0, 0, 4, 2, 2); | |
405 } | |
406 | |
407 /* obmc for 1 8x8 luma block */ | |
408 static inline void obmc_motion(MpegEncContext *s, | |
409 uint8_t *dest, uint8_t *src, | |
410 int src_x, int src_y, | |
411 op_pixels_func *pix_op, | |
412 int16_t mv[5][2]/* mid top left right bottom*/) | |
413 #define MID 0 | |
414 { | |
415 int i; | |
416 uint8_t *ptr[5]; | |
417 | |
418 assert(s->quarter_sample==0); | |
419 | |
420 for(i=0; i<5; i++){ | |
421 if(i && mv[i][0]==mv[MID][0] && mv[i][1]==mv[MID][1]){ | |
422 ptr[i]= ptr[MID]; | |
423 }else{ | |
424 ptr[i]= s->obmc_scratchpad + 8*(i&1) + s->linesize*8*(i>>1); | |
425 hpel_motion(s, ptr[i], src, 0, 0, | |
426 src_x, src_y, | |
427 s->width, s->height, s->linesize, | |
428 s->h_edge_pos, s->v_edge_pos, | |
429 8, 8, pix_op, | |
430 mv[i][0], mv[i][1]); | |
431 } | |
432 } | |
433 | |
434 put_obmc(dest, ptr, s->linesize); | |
435 } | |
436 | |
437 static inline void qpel_motion(MpegEncContext *s, | |
438 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, | |
439 int field_based, int bottom_field, int field_select, | |
440 uint8_t **ref_picture, op_pixels_func (*pix_op)[4], | |
441 qpel_mc_func (*qpix_op)[16], | |
442 int motion_x, int motion_y, int h) | |
443 { | |
444 uint8_t *ptr_y, *ptr_cb, *ptr_cr; | |
445 int dxy, uvdxy, mx, my, src_x, src_y, uvsrc_x, uvsrc_y, v_edge_pos, linesize, uvlinesize; | |
446 | |
447 dxy = ((motion_y & 3) << 2) | (motion_x & 3); | |
448 src_x = s->mb_x * 16 + (motion_x >> 2); | |
449 src_y = s->mb_y * (16 >> field_based) + (motion_y >> 2); | |
450 | |
451 v_edge_pos = s->v_edge_pos >> field_based; | |
452 linesize = s->linesize << field_based; | |
453 uvlinesize = s->uvlinesize << field_based; | |
454 | |
455 if(field_based){ | |
456 mx= motion_x/2; | |
457 my= motion_y>>1; | |
458 }else if(s->workaround_bugs&FF_BUG_QPEL_CHROMA2){ | |
459 static const int rtab[8]= {0,0,1,1,0,0,0,1}; | |
460 mx= (motion_x>>1) + rtab[motion_x&7]; | |
461 my= (motion_y>>1) + rtab[motion_y&7]; | |
462 }else if(s->workaround_bugs&FF_BUG_QPEL_CHROMA){ | |
463 mx= (motion_x>>1)|(motion_x&1); | |
464 my= (motion_y>>1)|(motion_y&1); | |
465 }else{ | |
466 mx= motion_x/2; | |
467 my= motion_y/2; | |
468 } | |
469 mx= (mx>>1)|(mx&1); | |
470 my= (my>>1)|(my&1); | |
471 | |
472 uvdxy= (mx&1) | ((my&1)<<1); | |
473 mx>>=1; | |
474 my>>=1; | |
475 | |
476 uvsrc_x = s->mb_x * 8 + mx; | |
477 uvsrc_y = s->mb_y * (8 >> field_based) + my; | |
478 | |
479 ptr_y = ref_picture[0] + src_y * linesize + src_x; | |
480 ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; | |
481 ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; | |
482 | |
483 if( (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 16 | |
484 || (unsigned)src_y > v_edge_pos - (motion_y&3) - h ){ | |
485 ff_emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based, | |
486 src_x, src_y<<field_based, s->h_edge_pos, s->v_edge_pos); | |
487 ptr_y= s->edge_emu_buffer; | |
5433
ce0db8111f94
make grayscale only decoding checks in inner loops compiletime killable
michael
parents:
5428
diff
changeset
|
488 if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ |
5204 | 489 uint8_t *uvbuf= s->edge_emu_buffer + 18*s->linesize; |
490 ff_emulated_edge_mc(uvbuf, ptr_cb, s->uvlinesize, 9, 9 + field_based, | |
491 uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); | |
492 ff_emulated_edge_mc(uvbuf + 16, ptr_cr, s->uvlinesize, 9, 9 + field_based, | |
493 uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); | |
494 ptr_cb= uvbuf; | |
495 ptr_cr= uvbuf + 16; | |
496 } | |
497 } | |
498 | |
499 if(!field_based) | |
500 qpix_op[0][dxy](dest_y, ptr_y, linesize); | |
501 else{ | |
502 if(bottom_field){ | |
503 dest_y += s->linesize; | |
504 dest_cb+= s->uvlinesize; | |
505 dest_cr+= s->uvlinesize; | |
506 } | |
507 | |
508 if(field_select){ | |
509 ptr_y += s->linesize; | |
510 ptr_cb += s->uvlinesize; | |
511 ptr_cr += s->uvlinesize; | |
512 } | |
513 //damn interlaced mode | |
514 //FIXME boundary mirroring is not exactly correct here | |
515 qpix_op[1][dxy](dest_y , ptr_y , linesize); | |
516 qpix_op[1][dxy](dest_y+8, ptr_y+8, linesize); | |
517 } | |
5433
ce0db8111f94
make grayscale only decoding checks in inner loops compiletime killable
michael
parents:
5428
diff
changeset
|
518 if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ |
5204 | 519 pix_op[1][uvdxy](dest_cr, ptr_cr, uvlinesize, h >> 1); |
520 pix_op[1][uvdxy](dest_cb, ptr_cb, uvlinesize, h >> 1); | |
521 } | |
522 } | |
523 | |
524 /** | |
5428 | 525 * h263 chroma 4mv motion compensation. |
5204 | 526 */ |
527 static inline void chroma_4mv_motion(MpegEncContext *s, | |
528 uint8_t *dest_cb, uint8_t *dest_cr, | |
529 uint8_t **ref_picture, | |
530 op_pixels_func *pix_op, | |
531 int mx, int my){ | |
532 int dxy, emu=0, src_x, src_y, offset; | |
533 uint8_t *ptr; | |
534 | |
535 /* In case of 8X8, we construct a single chroma motion vector | |
536 with a special rounding */ | |
537 mx= ff_h263_round_chroma(mx); | |
538 my= ff_h263_round_chroma(my); | |
539 | |
540 dxy = ((my & 1) << 1) | (mx & 1); | |
541 mx >>= 1; | |
542 my >>= 1; | |
543 | |
544 src_x = s->mb_x * 8 + mx; | |
545 src_y = s->mb_y * 8 + my; | |
546 src_x = av_clip(src_x, -8, s->width/2); | |
547 if (src_x == s->width/2) | |
548 dxy &= ~1; | |
549 src_y = av_clip(src_y, -8, s->height/2); | |
550 if (src_y == s->height/2) | |
551 dxy &= ~2; | |
552 | |
553 offset = (src_y * (s->uvlinesize)) + src_x; | |
554 ptr = ref_picture[1] + offset; | |
555 if(s->flags&CODEC_FLAG_EMU_EDGE){ | |
556 if( (unsigned)src_x > (s->h_edge_pos>>1) - (dxy &1) - 8 | |
557 || (unsigned)src_y > (s->v_edge_pos>>1) - (dxy>>1) - 8){ | |
558 ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); | |
559 ptr= s->edge_emu_buffer; | |
560 emu=1; | |
561 } | |
562 } | |
563 pix_op[dxy](dest_cb, ptr, s->uvlinesize, 8); | |
564 | |
565 ptr = ref_picture[2] + offset; | |
566 if(emu){ | |
567 ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); | |
568 ptr= s->edge_emu_buffer; | |
569 } | |
570 pix_op[dxy](dest_cr, ptr, s->uvlinesize, 8); | |
571 } | |
572 | |
573 static inline void prefetch_motion(MpegEncContext *s, uint8_t **pix, int dir){ | |
574 /* fetch pixels for estimated mv 4 macroblocks ahead | |
575 * optimized for 64byte cache lines */ | |
576 const int shift = s->quarter_sample ? 2 : 1; | |
577 const int mx= (s->mv[dir][0][0]>>shift) + 16*s->mb_x + 8; | |
578 const int my= (s->mv[dir][0][1]>>shift) + 16*s->mb_y; | |
579 int off= mx + (my + (s->mb_x&3)*4)*s->linesize + 64; | |
580 s->dsp.prefetch(pix[0]+off, s->linesize, 4); | |
581 off= (mx>>1) + ((my>>1) + (s->mb_x&7))*s->uvlinesize + 64; | |
582 s->dsp.prefetch(pix[1]+off, pix[2]-pix[1], 2); | |
583 } | |
584 | |
585 /** | |
586 * motion compensation of a single macroblock | |
587 * @param s context | |
588 * @param dest_y luma destination pointer | |
589 * @param dest_cb chroma cb/u destination pointer | |
590 * @param dest_cr chroma cr/v destination pointer | |
591 * @param dir direction (0->forward, 1->backward) | |
592 * @param ref_picture array[3] of pointers to the 3 planes of the reference picture | |
593 * @param pic_op halfpel motion compensation function (average or put normally) | |
594 * @param pic_op qpel motion compensation function (average or put normally) | |
595 * the motion vectors are taken from s->mv and the MV type from s->mv_type | |
596 */ | |
597 static inline void MPV_motion(MpegEncContext *s, | |
598 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, | |
599 int dir, uint8_t **ref_picture, | |
600 op_pixels_func (*pix_op)[4], qpel_mc_func (*qpix_op)[16]) | |
601 { | |
602 int dxy, mx, my, src_x, src_y, motion_x, motion_y; | |
603 int mb_x, mb_y, i; | |
604 uint8_t *ptr, *dest; | |
605 | |
606 mb_x = s->mb_x; | |
607 mb_y = s->mb_y; | |
608 | |
609 prefetch_motion(s, ref_picture, dir); | |
610 | |
611 if(s->obmc && s->pict_type != B_TYPE){ | |
612 int16_t mv_cache[4][4][2]; | |
613 const int xy= s->mb_x + s->mb_y*s->mb_stride; | |
614 const int mot_stride= s->b8_stride; | |
615 const int mot_xy= mb_x*2 + mb_y*2*mot_stride; | |
616 | |
617 assert(!s->mb_skipped); | |
618 | |
619 memcpy(mv_cache[1][1], s->current_picture.motion_val[0][mot_xy ], sizeof(int16_t)*4); | |
620 memcpy(mv_cache[2][1], s->current_picture.motion_val[0][mot_xy+mot_stride], sizeof(int16_t)*4); | |
621 memcpy(mv_cache[3][1], s->current_picture.motion_val[0][mot_xy+mot_stride], sizeof(int16_t)*4); | |
622 | |
623 if(mb_y==0 || IS_INTRA(s->current_picture.mb_type[xy-s->mb_stride])){ | |
624 memcpy(mv_cache[0][1], mv_cache[1][1], sizeof(int16_t)*4); | |
625 }else{ | |
626 memcpy(mv_cache[0][1], s->current_picture.motion_val[0][mot_xy-mot_stride], sizeof(int16_t)*4); | |
627 } | |
628 | |
629 if(mb_x==0 || IS_INTRA(s->current_picture.mb_type[xy-1])){ | |
630 *(int32_t*)mv_cache[1][0]= *(int32_t*)mv_cache[1][1]; | |
631 *(int32_t*)mv_cache[2][0]= *(int32_t*)mv_cache[2][1]; | |
632 }else{ | |
633 *(int32_t*)mv_cache[1][0]= *(int32_t*)s->current_picture.motion_val[0][mot_xy-1]; | |
634 *(int32_t*)mv_cache[2][0]= *(int32_t*)s->current_picture.motion_val[0][mot_xy-1+mot_stride]; | |
635 } | |
636 | |
637 if(mb_x+1>=s->mb_width || IS_INTRA(s->current_picture.mb_type[xy+1])){ | |
638 *(int32_t*)mv_cache[1][3]= *(int32_t*)mv_cache[1][2]; | |
639 *(int32_t*)mv_cache[2][3]= *(int32_t*)mv_cache[2][2]; | |
640 }else{ | |
641 *(int32_t*)mv_cache[1][3]= *(int32_t*)s->current_picture.motion_val[0][mot_xy+2]; | |
642 *(int32_t*)mv_cache[2][3]= *(int32_t*)s->current_picture.motion_val[0][mot_xy+2+mot_stride]; | |
643 } | |
644 | |
645 mx = 0; | |
646 my = 0; | |
647 for(i=0;i<4;i++) { | |
648 const int x= (i&1)+1; | |
649 const int y= (i>>1)+1; | |
650 int16_t mv[5][2]= { | |
651 {mv_cache[y][x ][0], mv_cache[y][x ][1]}, | |
652 {mv_cache[y-1][x][0], mv_cache[y-1][x][1]}, | |
653 {mv_cache[y][x-1][0], mv_cache[y][x-1][1]}, | |
654 {mv_cache[y][x+1][0], mv_cache[y][x+1][1]}, | |
655 {mv_cache[y+1][x][0], mv_cache[y+1][x][1]}}; | |
656 //FIXME cleanup | |
657 obmc_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize, | |
658 ref_picture[0], | |
659 mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8, | |
660 pix_op[1], | |
661 mv); | |
662 | |
663 mx += mv[0][0]; | |
664 my += mv[0][1]; | |
665 } | |
5433
ce0db8111f94
make grayscale only decoding checks in inner loops compiletime killable
michael
parents:
5428
diff
changeset
|
666 if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY)) |
5204 | 667 chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my); |
668 | |
669 return; | |
670 } | |
671 | |
672 switch(s->mv_type) { | |
673 case MV_TYPE_16X16: | |
674 if(s->mcsel){ | |
675 if(s->real_sprite_warping_points==1){ | |
676 gmc1_motion(s, dest_y, dest_cb, dest_cr, | |
677 ref_picture); | |
678 }else{ | |
679 gmc_motion(s, dest_y, dest_cb, dest_cr, | |
680 ref_picture); | |
681 } | |
682 }else if(s->quarter_sample){ | |
683 qpel_motion(s, dest_y, dest_cb, dest_cr, | |
684 0, 0, 0, | |
685 ref_picture, pix_op, qpix_op, | |
686 s->mv[dir][0][0], s->mv[dir][0][1], 16); | |
687 }else if(ENABLE_WMV2 && s->mspel){ | |
688 ff_mspel_motion(s, dest_y, dest_cb, dest_cr, | |
689 ref_picture, pix_op, | |
690 s->mv[dir][0][0], s->mv[dir][0][1], 16); | |
691 }else | |
692 { | |
693 mpeg_motion(s, dest_y, dest_cb, dest_cr, | |
694 0, 0, 0, | |
695 ref_picture, pix_op, | |
696 s->mv[dir][0][0], s->mv[dir][0][1], 16); | |
697 } | |
698 break; | |
699 case MV_TYPE_8X8: | |
700 mx = 0; | |
701 my = 0; | |
702 if(s->quarter_sample){ | |
703 for(i=0;i<4;i++) { | |
704 motion_x = s->mv[dir][i][0]; | |
705 motion_y = s->mv[dir][i][1]; | |
706 | |
707 dxy = ((motion_y & 3) << 2) | (motion_x & 3); | |
708 src_x = mb_x * 16 + (motion_x >> 2) + (i & 1) * 8; | |
709 src_y = mb_y * 16 + (motion_y >> 2) + (i >>1) * 8; | |
710 | |
711 /* WARNING: do no forget half pels */ | |
712 src_x = av_clip(src_x, -16, s->width); | |
713 if (src_x == s->width) | |
714 dxy &= ~3; | |
715 src_y = av_clip(src_y, -16, s->height); | |
716 if (src_y == s->height) | |
717 dxy &= ~12; | |
718 | |
719 ptr = ref_picture[0] + (src_y * s->linesize) + (src_x); | |
720 if(s->flags&CODEC_FLAG_EMU_EDGE){ | |
721 if( (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 8 | |
722 || (unsigned)src_y > s->v_edge_pos - (motion_y&3) - 8 ){ | |
723 ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->linesize, 9, 9, src_x, src_y, s->h_edge_pos, s->v_edge_pos); | |
724 ptr= s->edge_emu_buffer; | |
725 } | |
726 } | |
727 dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize; | |
728 qpix_op[1][dxy](dest, ptr, s->linesize); | |
729 | |
730 mx += s->mv[dir][i][0]/2; | |
731 my += s->mv[dir][i][1]/2; | |
732 } | |
733 }else{ | |
734 for(i=0;i<4;i++) { | |
735 hpel_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize, | |
736 ref_picture[0], 0, 0, | |
737 mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8, | |
738 s->width, s->height, s->linesize, | |
739 s->h_edge_pos, s->v_edge_pos, | |
740 8, 8, pix_op[1], | |
741 s->mv[dir][i][0], s->mv[dir][i][1]); | |
742 | |
743 mx += s->mv[dir][i][0]; | |
744 my += s->mv[dir][i][1]; | |
745 } | |
746 } | |
747 | |
5433
ce0db8111f94
make grayscale only decoding checks in inner loops compiletime killable
michael
parents:
5428
diff
changeset
|
748 if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY)) |
5204 | 749 chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my); |
750 break; | |
751 case MV_TYPE_FIELD: | |
752 if (s->picture_structure == PICT_FRAME) { | |
753 if(s->quarter_sample){ | |
754 for(i=0; i<2; i++){ | |
755 qpel_motion(s, dest_y, dest_cb, dest_cr, | |
756 1, i, s->field_select[dir][i], | |
757 ref_picture, pix_op, qpix_op, | |
758 s->mv[dir][i][0], s->mv[dir][i][1], 8); | |
759 } | |
760 }else{ | |
761 /* top field */ | |
762 mpeg_motion(s, dest_y, dest_cb, dest_cr, | |
763 1, 0, s->field_select[dir][0], | |
764 ref_picture, pix_op, | |
765 s->mv[dir][0][0], s->mv[dir][0][1], 8); | |
766 /* bottom field */ | |
767 mpeg_motion(s, dest_y, dest_cb, dest_cr, | |
768 1, 1, s->field_select[dir][1], | |
769 ref_picture, pix_op, | |
770 s->mv[dir][1][0], s->mv[dir][1][1], 8); | |
771 } | |
772 } else { | |
773 if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != B_TYPE && !s->first_field){ | |
774 ref_picture= s->current_picture_ptr->data; | |
775 } | |
776 | |
777 mpeg_motion(s, dest_y, dest_cb, dest_cr, | |
778 0, 0, s->field_select[dir][0], | |
779 ref_picture, pix_op, | |
780 s->mv[dir][0][0], s->mv[dir][0][1], 16); | |
781 } | |
782 break; | |
783 case MV_TYPE_16X8: | |
784 for(i=0; i<2; i++){ | |
785 uint8_t ** ref2picture; | |
786 | |
787 if(s->picture_structure == s->field_select[dir][i] + 1 || s->pict_type == B_TYPE || s->first_field){ | |
788 ref2picture= ref_picture; | |
789 }else{ | |
790 ref2picture= s->current_picture_ptr->data; | |
791 } | |
792 | |
793 mpeg_motion(s, dest_y, dest_cb, dest_cr, | |
794 0, 0, s->field_select[dir][i], | |
795 ref2picture, pix_op, | |
796 s->mv[dir][i][0], s->mv[dir][i][1] + 16*i, 8); | |
797 | |
798 dest_y += 16*s->linesize; | |
799 dest_cb+= (16>>s->chroma_y_shift)*s->uvlinesize; | |
800 dest_cr+= (16>>s->chroma_y_shift)*s->uvlinesize; | |
801 } | |
802 break; | |
803 case MV_TYPE_DMV: | |
804 if(s->picture_structure == PICT_FRAME){ | |
805 for(i=0; i<2; i++){ | |
806 int j; | |
807 for(j=0; j<2; j++){ | |
808 mpeg_motion(s, dest_y, dest_cb, dest_cr, | |
809 1, j, j^i, | |
810 ref_picture, pix_op, | |
811 s->mv[dir][2*i + j][0], s->mv[dir][2*i + j][1], 8); | |
812 } | |
813 pix_op = s->dsp.avg_pixels_tab; | |
814 } | |
815 }else{ | |
816 for(i=0; i<2; i++){ | |
817 mpeg_motion(s, dest_y, dest_cb, dest_cr, | |
818 0, 0, s->picture_structure != i+1, | |
819 ref_picture, pix_op, | |
820 s->mv[dir][2*i][0],s->mv[dir][2*i][1],16); | |
821 | |
822 // after put we make avg of the same block | |
823 pix_op=s->dsp.avg_pixels_tab; | |
824 | |
825 //opposite parity is always in the same frame if this is second field | |
826 if(!s->first_field){ | |
827 ref_picture = s->current_picture_ptr->data; | |
828 } | |
829 } | |
830 } | |
831 break; | |
832 default: assert(0); | |
833 } | |
834 } | |
835 | |
5830
1d83e9c34641
Add FFMPEG_ prefix to all multiple inclusion guards.
diego
parents:
5433
diff
changeset
|
836 #endif /* FFMPEG_MPEGVIDEO_COMMON_H */ |