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
|
|
30 #ifndef MPEGVIDEO_COMMON_H
|
|
31 #define MPEGVIDEO_COMMON_H
|
|
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
|
|
107 if(s->flags&CODEC_FLAG_GRAY) return;
|
|
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
|
|
176 if(s->flags&CODEC_FLAG_GRAY) return;
|
|
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;
|
|
321 if(!(s->flags&CODEC_FLAG_GRAY)){
|
|
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
|
|
346 if(!(s->flags&CODEC_FLAG_GRAY)){
|
|
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;
|
|
488 if(!(s->flags&CODEC_FLAG_GRAY)){
|
|
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 }
|
|
518 if(!(s->flags&CODEC_FLAG_GRAY)){
|
|
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 /**
|
|
525 * h263 chorma 4mv motion compensation.
|
|
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 }
|
|
666 if(!(s->flags&CODEC_FLAG_GRAY))
|
|
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
|
|
748 if(!(s->flags&CODEC_FLAG_GRAY))
|
|
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
|
|
836 #endif /* MPEGVIDEO_COMMON_H */
|