2 * Copyright (c) 2000,2001 Fabrice Bellard
3 * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
5 * 4MV & hq & B-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at>
7 * This file is part of Libav.
9 * Libav is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * Libav is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with Libav; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "libavutil/internal.h"
29 #include "mpegvideo.h"
34 static void gmc1_motion(MpegEncContext
*s
,
35 uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
,
36 uint8_t **ref_picture
)
39 int offset
, src_x
, src_y
, linesize
, uvlinesize
;
40 int motion_x
, motion_y
;
43 motion_x
= s
->sprite_offset
[0][0];
44 motion_y
= s
->sprite_offset
[0][1];
45 src_x
= s
->mb_x
* 16 + (motion_x
>> (s
->sprite_warping_accuracy
+1));
46 src_y
= s
->mb_y
* 16 + (motion_y
>> (s
->sprite_warping_accuracy
+1));
47 motion_x
<<=(3-s
->sprite_warping_accuracy
);
48 motion_y
<<=(3-s
->sprite_warping_accuracy
);
49 src_x
= av_clip(src_x
, -16, s
->width
);
50 if (src_x
== s
->width
)
52 src_y
= av_clip(src_y
, -16, s
->height
);
53 if (src_y
== s
->height
)
56 linesize
= s
->linesize
;
57 uvlinesize
= s
->uvlinesize
;
59 ptr
= ref_picture
[0] + (src_y
* linesize
) + src_x
;
61 if(s
->flags
&CODEC_FLAG_EMU_EDGE
){
62 if( (unsigned)src_x
>= FFMAX(s
->h_edge_pos
- 17, 0)
63 || (unsigned)src_y
>= FFMAX(s
->v_edge_pos
- 17, 0)){
64 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
, linesize
, 17, 17, src_x
, src_y
, s
->h_edge_pos
, s
->v_edge_pos
);
65 ptr
= s
->edge_emu_buffer
;
69 if((motion_x
|motion_y
)&7){
70 s
->dsp
.gmc1(dest_y
, ptr
, linesize
, 16, motion_x
&15, motion_y
&15, 128 - s
->no_rounding
);
71 s
->dsp
.gmc1(dest_y
+8, ptr
+8, linesize
, 16, motion_x
&15, motion_y
&15, 128 - s
->no_rounding
);
75 dxy
= ((motion_x
>>3)&1) | ((motion_y
>>2)&2);
77 s
->dsp
.put_no_rnd_pixels_tab
[0][dxy
](dest_y
, ptr
, linesize
, 16);
79 s
->dsp
.put_pixels_tab
[0][dxy
](dest_y
, ptr
, linesize
, 16);
83 if(CONFIG_GRAY
&& s
->flags
&CODEC_FLAG_GRAY
) return;
85 motion_x
= s
->sprite_offset
[1][0];
86 motion_y
= s
->sprite_offset
[1][1];
87 src_x
= s
->mb_x
* 8 + (motion_x
>> (s
->sprite_warping_accuracy
+1));
88 src_y
= s
->mb_y
* 8 + (motion_y
>> (s
->sprite_warping_accuracy
+1));
89 motion_x
<<=(3-s
->sprite_warping_accuracy
);
90 motion_y
<<=(3-s
->sprite_warping_accuracy
);
91 src_x
= av_clip(src_x
, -8, s
->width
>>1);
92 if (src_x
== s
->width
>>1)
94 src_y
= av_clip(src_y
, -8, s
->height
>>1);
95 if (src_y
== s
->height
>>1)
98 offset
= (src_y
* uvlinesize
) + src_x
;
99 ptr
= ref_picture
[1] + offset
;
100 if(s
->flags
&CODEC_FLAG_EMU_EDGE
){
101 if( (unsigned)src_x
>= FFMAX((s
->h_edge_pos
>>1) - 9, 0)
102 || (unsigned)src_y
>= FFMAX((s
->v_edge_pos
>>1) - 9, 0)){
103 s
->vdsp
.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);
104 ptr
= s
->edge_emu_buffer
;
108 s
->dsp
.gmc1(dest_cb
, ptr
, uvlinesize
, 8, motion_x
&15, motion_y
&15, 128 - s
->no_rounding
);
110 ptr
= ref_picture
[2] + offset
;
112 s
->vdsp
.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);
113 ptr
= s
->edge_emu_buffer
;
115 s
->dsp
.gmc1(dest_cr
, ptr
, uvlinesize
, 8, motion_x
&15, motion_y
&15, 128 - s
->no_rounding
);
120 static void gmc_motion(MpegEncContext
*s
,
121 uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
,
122 uint8_t **ref_picture
)
125 int linesize
, uvlinesize
;
126 const int a
= s
->sprite_warping_accuracy
;
129 linesize
= s
->linesize
;
130 uvlinesize
= s
->uvlinesize
;
132 ptr
= ref_picture
[0];
134 ox
= s
->sprite_offset
[0][0] + s
->sprite_delta
[0][0]*s
->mb_x
*16 + s
->sprite_delta
[0][1]*s
->mb_y
*16;
135 oy
= s
->sprite_offset
[0][1] + s
->sprite_delta
[1][0]*s
->mb_x
*16 + s
->sprite_delta
[1][1]*s
->mb_y
*16;
137 s
->dsp
.gmc(dest_y
, ptr
, linesize
, 16,
140 s
->sprite_delta
[0][0], s
->sprite_delta
[0][1],
141 s
->sprite_delta
[1][0], s
->sprite_delta
[1][1],
142 a
+1, (1<<(2*a
+1)) - s
->no_rounding
,
143 s
->h_edge_pos
, s
->v_edge_pos
);
144 s
->dsp
.gmc(dest_y
+8, ptr
, linesize
, 16,
145 ox
+ s
->sprite_delta
[0][0]*8,
146 oy
+ s
->sprite_delta
[1][0]*8,
147 s
->sprite_delta
[0][0], s
->sprite_delta
[0][1],
148 s
->sprite_delta
[1][0], s
->sprite_delta
[1][1],
149 a
+1, (1<<(2*a
+1)) - s
->no_rounding
,
150 s
->h_edge_pos
, s
->v_edge_pos
);
152 if(CONFIG_GRAY
&& s
->flags
&CODEC_FLAG_GRAY
) return;
154 ox
= s
->sprite_offset
[1][0] + s
->sprite_delta
[0][0]*s
->mb_x
*8 + s
->sprite_delta
[0][1]*s
->mb_y
*8;
155 oy
= s
->sprite_offset
[1][1] + s
->sprite_delta
[1][0]*s
->mb_x
*8 + s
->sprite_delta
[1][1]*s
->mb_y
*8;
157 ptr
= ref_picture
[1];
158 s
->dsp
.gmc(dest_cb
, ptr
, uvlinesize
, 8,
161 s
->sprite_delta
[0][0], s
->sprite_delta
[0][1],
162 s
->sprite_delta
[1][0], s
->sprite_delta
[1][1],
163 a
+1, (1<<(2*a
+1)) - s
->no_rounding
,
164 s
->h_edge_pos
>>1, s
->v_edge_pos
>>1);
166 ptr
= ref_picture
[2];
167 s
->dsp
.gmc(dest_cr
, ptr
, uvlinesize
, 8,
170 s
->sprite_delta
[0][0], s
->sprite_delta
[0][1],
171 s
->sprite_delta
[1][0], s
->sprite_delta
[1][1],
172 a
+1, (1<<(2*a
+1)) - s
->no_rounding
,
173 s
->h_edge_pos
>>1, s
->v_edge_pos
>>1);
176 static inline int hpel_motion(MpegEncContext
*s
,
177 uint8_t *dest
, uint8_t *src
,
178 int src_x
, int src_y
,
179 op_pixels_func
*pix_op
,
180 int motion_x
, int motion_y
)
185 src_x
+= motion_x
>> 1;
186 src_y
+= motion_y
>> 1;
188 /* WARNING: do no forget half pels */
189 src_x
= av_clip(src_x
, -16, s
->width
); //FIXME unneeded for emu?
190 if (src_x
!= s
->width
)
192 src_y
= av_clip(src_y
, -16, s
->height
);
193 if (src_y
!= s
->height
)
194 dxy
|= (motion_y
& 1) << 1;
195 src
+= src_y
* s
->linesize
+ src_x
;
197 if(s
->unrestricted_mv
&& (s
->flags
&CODEC_FLAG_EMU_EDGE
)){
198 if( (unsigned)src_x
> FFMAX(s
->h_edge_pos
- (motion_x
&1) - 8, 0)
199 || (unsigned)src_y
> FFMAX(s
->v_edge_pos
- (motion_y
&1) - 8, 0)){
200 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, src
, s
->linesize
, 9, 9,
201 src_x
, src_y
, s
->h_edge_pos
, s
->v_edge_pos
);
202 src
= s
->edge_emu_buffer
;
206 pix_op
[dxy
](dest
, src
, s
->linesize
, 8);
210 static av_always_inline
211 void mpeg_motion_internal(MpegEncContext
*s
,
212 uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
,
213 int field_based
, int bottom_field
, int field_select
,
214 uint8_t **ref_picture
, op_pixels_func (*pix_op
)[4],
215 int motion_x
, int motion_y
, int h
, int is_mpeg12
, int mb_y
)
217 uint8_t *ptr_y
, *ptr_cb
, *ptr_cr
;
218 int dxy
, uvdxy
, mx
, my
, src_x
, src_y
,
219 uvsrc_x
, uvsrc_y
, v_edge_pos
, uvlinesize
, linesize
;
222 if(s
->quarter_sample
)
229 v_edge_pos
= s
->v_edge_pos
>> field_based
;
230 linesize
= s
->current_picture
.f
.linesize
[0] << field_based
;
231 uvlinesize
= s
->current_picture
.f
.linesize
[1] << field_based
;
233 dxy
= ((motion_y
& 1) << 1) | (motion_x
& 1);
234 src_x
= s
->mb_x
* 16 + (motion_x
>> 1);
235 src_y
=( mb_y
<<(4-field_based
)) + (motion_y
>> 1);
237 if (!is_mpeg12
&& s
->out_format
== FMT_H263
) {
238 if((s
->workaround_bugs
& FF_BUG_HPEL_CHROMA
) && field_based
){
239 mx
= (motion_x
>>1)|(motion_x
&1);
241 uvdxy
= ((my
& 1) << 1) | (mx
& 1);
242 uvsrc_x
= s
->mb_x
* 8 + (mx
>> 1);
243 uvsrc_y
=( mb_y
<<(3-field_based
))+ (my
>> 1);
245 uvdxy
= dxy
| (motion_y
& 2) | ((motion_x
& 2) >> 1);
249 }else if(!is_mpeg12
&& s
->out_format
== FMT_H261
){//even chroma mv's are full pel in H261
253 uvsrc_x
= s
->mb_x
*8 + mx
;
254 uvsrc_y
= mb_y
*8 + my
;
256 if(s
->chroma_y_shift
){
259 uvdxy
= ((my
& 1) << 1) | (mx
& 1);
260 uvsrc_x
= s
->mb_x
* 8 + (mx
>> 1);
261 uvsrc_y
=( mb_y
<<(3-field_based
))+ (my
>> 1);
263 if(s
->chroma_x_shift
){
266 uvdxy
= ((motion_y
& 1) << 1) | (mx
& 1);
267 uvsrc_x
= s
->mb_x
* 8 + (mx
>> 1);
278 ptr_y
= ref_picture
[0] + src_y
* linesize
+ src_x
;
279 ptr_cb
= ref_picture
[1] + uvsrc_y
* uvlinesize
+ uvsrc_x
;
280 ptr_cr
= ref_picture
[2] + uvsrc_y
* uvlinesize
+ uvsrc_x
;
282 if( (unsigned)src_x
> FFMAX(s
->h_edge_pos
- (motion_x
&1) - 16, 0)
283 || (unsigned)src_y
> FFMAX( v_edge_pos
- (motion_y
&1) - h
, 0)){
284 if(is_mpeg12
|| s
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
||
285 s
->codec_id
== AV_CODEC_ID_MPEG1VIDEO
){
286 av_log(s
->avctx
,AV_LOG_DEBUG
,
287 "MPEG motion vector out of boundary (%d %d)\n", src_x
, src_y
);
290 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr_y
, s
->linesize
,
292 src_x
, src_y
<<field_based
,
293 s
->h_edge_pos
, s
->v_edge_pos
);
294 ptr_y
= s
->edge_emu_buffer
;
295 if(!CONFIG_GRAY
|| !(s
->flags
&CODEC_FLAG_GRAY
)){
296 uint8_t *uvbuf
= s
->edge_emu_buffer
+18*s
->linesize
;
297 s
->vdsp
.emulated_edge_mc(uvbuf
,
298 ptr_cb
, s
->uvlinesize
,
300 uvsrc_x
, uvsrc_y
<<field_based
,
301 s
->h_edge_pos
>>1, s
->v_edge_pos
>>1);
302 s
->vdsp
.emulated_edge_mc(uvbuf
+16,
303 ptr_cr
, s
->uvlinesize
,
305 uvsrc_x
, uvsrc_y
<<field_based
,
306 s
->h_edge_pos
>>1, s
->v_edge_pos
>>1);
312 if(bottom_field
){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.data
313 dest_y
+= s
->linesize
;
314 dest_cb
+= s
->uvlinesize
;
315 dest_cr
+= s
->uvlinesize
;
319 ptr_y
+= s
->linesize
;
320 ptr_cb
+= s
->uvlinesize
;
321 ptr_cr
+= s
->uvlinesize
;
324 pix_op
[0][dxy
](dest_y
, ptr_y
, linesize
, h
);
326 if(!CONFIG_GRAY
|| !(s
->flags
&CODEC_FLAG_GRAY
)){
327 pix_op
[s
->chroma_x_shift
][uvdxy
]
328 (dest_cb
, ptr_cb
, uvlinesize
, h
>> s
->chroma_y_shift
);
329 pix_op
[s
->chroma_x_shift
][uvdxy
]
330 (dest_cr
, ptr_cr
, uvlinesize
, h
>> s
->chroma_y_shift
);
332 if(!is_mpeg12
&& (CONFIG_H261_ENCODER
|| CONFIG_H261_DECODER
) &&
333 s
->out_format
== FMT_H261
){
334 ff_h261_loop_filter(s
);
337 /* apply one mpeg motion vector to the three components */
338 static void mpeg_motion(MpegEncContext
*s
,
339 uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
,
340 int field_select
, uint8_t **ref_picture
,
341 op_pixels_func (*pix_op
)[4],
342 int motion_x
, int motion_y
, int h
, int mb_y
)
345 if(s
->out_format
== FMT_MPEG1
)
346 mpeg_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, 0, 0,
347 field_select
, ref_picture
, pix_op
,
348 motion_x
, motion_y
, h
, 1, mb_y
);
351 mpeg_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, 0, 0,
352 field_select
, ref_picture
, pix_op
,
353 motion_x
, motion_y
, h
, 0, mb_y
);
356 static void mpeg_motion_field(MpegEncContext
*s
, uint8_t *dest_y
,
357 uint8_t *dest_cb
, uint8_t *dest_cr
,
358 int bottom_field
, int field_select
,
359 uint8_t **ref_picture
,
360 op_pixels_func (*pix_op
)[4],
361 int motion_x
, int motion_y
, int h
, int mb_y
)
364 if(s
->out_format
== FMT_MPEG1
)
365 mpeg_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, 1,
366 bottom_field
, field_select
, ref_picture
, pix_op
,
367 motion_x
, motion_y
, h
, 1, mb_y
);
370 mpeg_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, 1,
371 bottom_field
, field_select
, ref_picture
, pix_op
,
372 motion_x
, motion_y
, h
, 0, mb_y
);
375 //FIXME move to dsputil, avg variant, 16x16 version
376 static inline void put_obmc(uint8_t *dst
, uint8_t *src
[5], int stride
){
378 uint8_t * const top
= src
[1];
379 uint8_t * const left
= src
[2];
380 uint8_t * const mid
= src
[0];
381 uint8_t * const right
= src
[3];
382 uint8_t * const bottom
= src
[4];
383 #define OBMC_FILTER(x, t, l, m, r, b)\
384 dst[x]= (t*top[x] + l*left[x] + m*mid[x] + r*right[x] + b*bottom[x] + 4)>>3
385 #define OBMC_FILTER4(x, t, l, m, r, b)\
386 OBMC_FILTER(x , t, l, m, r, b);\
387 OBMC_FILTER(x+1 , t, l, m, r, b);\
388 OBMC_FILTER(x +stride, t, l, m, r, b);\
389 OBMC_FILTER(x+1+stride, t, l, m, r, b);
392 OBMC_FILTER (x
, 2, 2, 4, 0, 0);
393 OBMC_FILTER (x
+1, 2, 1, 5, 0, 0);
394 OBMC_FILTER4(x
+2, 2, 1, 5, 0, 0);
395 OBMC_FILTER4(x
+4, 2, 0, 5, 1, 0);
396 OBMC_FILTER (x
+6, 2, 0, 5, 1, 0);
397 OBMC_FILTER (x
+7, 2, 0, 4, 2, 0);
399 OBMC_FILTER (x
, 1, 2, 5, 0, 0);
400 OBMC_FILTER (x
+1, 1, 2, 5, 0, 0);
401 OBMC_FILTER (x
+6, 1, 0, 5, 2, 0);
402 OBMC_FILTER (x
+7, 1, 0, 5, 2, 0);
404 OBMC_FILTER4(x
, 1, 2, 5, 0, 0);
405 OBMC_FILTER4(x
+2, 1, 1, 6, 0, 0);
406 OBMC_FILTER4(x
+4, 1, 0, 6, 1, 0);
407 OBMC_FILTER4(x
+6, 1, 0, 5, 2, 0);
409 OBMC_FILTER4(x
, 0, 2, 5, 0, 1);
410 OBMC_FILTER4(x
+2, 0, 1, 6, 0, 1);
411 OBMC_FILTER4(x
+4, 0, 0, 6, 1, 1);
412 OBMC_FILTER4(x
+6, 0, 0, 5, 2, 1);
414 OBMC_FILTER (x
, 0, 2, 5, 0, 1);
415 OBMC_FILTER (x
+1, 0, 2, 5, 0, 1);
416 OBMC_FILTER4(x
+2, 0, 1, 5, 0, 2);
417 OBMC_FILTER4(x
+4, 0, 0, 5, 1, 2);
418 OBMC_FILTER (x
+6, 0, 0, 5, 2, 1);
419 OBMC_FILTER (x
+7, 0, 0, 5, 2, 1);
421 OBMC_FILTER (x
, 0, 2, 4, 0, 2);
422 OBMC_FILTER (x
+1, 0, 1, 5, 0, 2);
423 OBMC_FILTER (x
+6, 0, 0, 5, 1, 2);
424 OBMC_FILTER (x
+7, 0, 0, 4, 2, 2);
427 /* obmc for 1 8x8 luma block */
428 static inline void obmc_motion(MpegEncContext
*s
,
429 uint8_t *dest
, uint8_t *src
,
430 int src_x
, int src_y
,
431 op_pixels_func
*pix_op
,
432 int16_t mv
[5][2]/* mid top left right bottom*/)
438 assert(s
->quarter_sample
==0);
441 if(i
&& mv
[i
][0]==mv
[MID
][0] && mv
[i
][1]==mv
[MID
][1]){
444 ptr
[i
]= s
->obmc_scratchpad
+ 8*(i
&1) + s
->linesize
*8*(i
>>1);
445 hpel_motion(s
, ptr
[i
], src
,
452 put_obmc(dest
, ptr
, s
->linesize
);
455 static inline void qpel_motion(MpegEncContext
*s
,
456 uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
,
457 int field_based
, int bottom_field
, int field_select
,
458 uint8_t **ref_picture
, op_pixels_func (*pix_op
)[4],
459 qpel_mc_func (*qpix_op
)[16],
460 int motion_x
, int motion_y
, int h
)
462 uint8_t *ptr_y
, *ptr_cb
, *ptr_cr
;
463 int dxy
, uvdxy
, mx
, my
, src_x
, src_y
, uvsrc_x
, uvsrc_y
, v_edge_pos
, linesize
, uvlinesize
;
465 dxy
= ((motion_y
& 3) << 2) | (motion_x
& 3);
466 src_x
= s
->mb_x
* 16 + (motion_x
>> 2);
467 src_y
= s
->mb_y
* (16 >> field_based
) + (motion_y
>> 2);
469 v_edge_pos
= s
->v_edge_pos
>> field_based
;
470 linesize
= s
->linesize
<< field_based
;
471 uvlinesize
= s
->uvlinesize
<< field_based
;
476 }else if(s
->workaround_bugs
&FF_BUG_QPEL_CHROMA2
){
477 static const int rtab
[8]= {0,0,1,1,0,0,0,1};
478 mx
= (motion_x
>>1) + rtab
[motion_x
&7];
479 my
= (motion_y
>>1) + rtab
[motion_y
&7];
480 }else if(s
->workaround_bugs
&FF_BUG_QPEL_CHROMA
){
481 mx
= (motion_x
>>1)|(motion_x
&1);
482 my
= (motion_y
>>1)|(motion_y
&1);
490 uvdxy
= (mx
&1) | ((my
&1)<<1);
494 uvsrc_x
= s
->mb_x
* 8 + mx
;
495 uvsrc_y
= s
->mb_y
* (8 >> field_based
) + my
;
497 ptr_y
= ref_picture
[0] + src_y
* linesize
+ src_x
;
498 ptr_cb
= ref_picture
[1] + uvsrc_y
* uvlinesize
+ uvsrc_x
;
499 ptr_cr
= ref_picture
[2] + uvsrc_y
* uvlinesize
+ uvsrc_x
;
501 if( (unsigned)src_x
> FFMAX(s
->h_edge_pos
- (motion_x
&3) - 16, 0)
502 || (unsigned)src_y
> FFMAX( v_edge_pos
- (motion_y
&3) - h
, 0)){
503 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr_y
, s
->linesize
,
504 17, 17+field_based
, src_x
, src_y
<<field_based
,
505 s
->h_edge_pos
, s
->v_edge_pos
);
506 ptr_y
= s
->edge_emu_buffer
;
507 if(!CONFIG_GRAY
|| !(s
->flags
&CODEC_FLAG_GRAY
)){
508 uint8_t *uvbuf
= s
->edge_emu_buffer
+ 18*s
->linesize
;
509 s
->vdsp
.emulated_edge_mc(uvbuf
, ptr_cb
, s
->uvlinesize
,
511 uvsrc_x
, uvsrc_y
<<field_based
,
512 s
->h_edge_pos
>>1, s
->v_edge_pos
>>1);
513 s
->vdsp
.emulated_edge_mc(uvbuf
+ 16, ptr_cr
, s
->uvlinesize
,
515 uvsrc_x
, uvsrc_y
<<field_based
,
516 s
->h_edge_pos
>>1, s
->v_edge_pos
>>1);
523 qpix_op
[0][dxy
](dest_y
, ptr_y
, linesize
);
526 dest_y
+= s
->linesize
;
527 dest_cb
+= s
->uvlinesize
;
528 dest_cr
+= s
->uvlinesize
;
532 ptr_y
+= s
->linesize
;
533 ptr_cb
+= s
->uvlinesize
;
534 ptr_cr
+= s
->uvlinesize
;
536 //damn interlaced mode
537 //FIXME boundary mirroring is not exactly correct here
538 qpix_op
[1][dxy
](dest_y
, ptr_y
, linesize
);
539 qpix_op
[1][dxy
](dest_y
+8, ptr_y
+8, linesize
);
541 if(!CONFIG_GRAY
|| !(s
->flags
&CODEC_FLAG_GRAY
)){
542 pix_op
[1][uvdxy
](dest_cr
, ptr_cr
, uvlinesize
, h
>> 1);
543 pix_op
[1][uvdxy
](dest_cb
, ptr_cb
, uvlinesize
, h
>> 1);
548 * h263 chroma 4mv motion compensation.
550 static void chroma_4mv_motion(MpegEncContext
*s
,
551 uint8_t *dest_cb
, uint8_t *dest_cr
,
552 uint8_t **ref_picture
,
553 op_pixels_func
*pix_op
,
556 int dxy
, emu
=0, src_x
, src_y
, offset
;
559 /* In case of 8X8, we construct a single chroma motion vector
560 with a special rounding */
561 mx
= ff_h263_round_chroma(mx
);
562 my
= ff_h263_round_chroma(my
);
564 dxy
= ((my
& 1) << 1) | (mx
& 1);
568 src_x
= s
->mb_x
* 8 + mx
;
569 src_y
= s
->mb_y
* 8 + my
;
570 src_x
= av_clip(src_x
, -8, (s
->width
>> 1));
571 if (src_x
== (s
->width
>> 1))
573 src_y
= av_clip(src_y
, -8, (s
->height
>> 1));
574 if (src_y
== (s
->height
>> 1))
577 offset
= src_y
* s
->uvlinesize
+ src_x
;
578 ptr
= ref_picture
[1] + offset
;
579 if(s
->flags
&CODEC_FLAG_EMU_EDGE
){
580 if( (unsigned)src_x
> FFMAX((s
->h_edge_pos
>>1) - (dxy
&1) - 8, 0)
581 || (unsigned)src_y
> FFMAX((s
->v_edge_pos
>>1) - (dxy
>>1) - 8, 0)){
582 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
, s
->uvlinesize
,
584 s
->h_edge_pos
>>1, s
->v_edge_pos
>>1);
585 ptr
= s
->edge_emu_buffer
;
589 pix_op
[dxy
](dest_cb
, ptr
, s
->uvlinesize
, 8);
591 ptr
= ref_picture
[2] + offset
;
593 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
, s
->uvlinesize
,
595 s
->h_edge_pos
>>1, s
->v_edge_pos
>>1);
596 ptr
= s
->edge_emu_buffer
;
598 pix_op
[dxy
](dest_cr
, ptr
, s
->uvlinesize
, 8);
601 static inline void prefetch_motion(MpegEncContext
*s
, uint8_t **pix
, int dir
){
602 /* fetch pixels for estimated mv 4 macroblocks ahead
603 * optimized for 64byte cache lines */
604 const int shift
= s
->quarter_sample
? 2 : 1;
605 const int mx
= (s
->mv
[dir
][0][0]>>shift
) + 16*s
->mb_x
+ 8;
606 const int my
= (s
->mv
[dir
][0][1]>>shift
) + 16*s
->mb_y
;
607 int off
= mx
+ (my
+ (s
->mb_x
&3)*4)*s
->linesize
+ 64;
608 s
->vdsp
.prefetch(pix
[0]+off
, s
->linesize
, 4);
609 off
= (mx
>>1) + ((my
>>1) + (s
->mb_x
&7))*s
->uvlinesize
+ 64;
610 s
->vdsp
.prefetch(pix
[1]+off
, pix
[2]-pix
[1], 2);
614 * motion compensation of a single macroblock
616 * @param dest_y luma destination pointer
617 * @param dest_cb chroma cb/u destination pointer
618 * @param dest_cr chroma cr/v destination pointer
619 * @param dir direction (0->forward, 1->backward)
620 * @param ref_picture array[3] of pointers to the 3 planes of the reference picture
621 * @param pix_op halfpel motion compensation function (average or put normally)
622 * @param qpix_op qpel motion compensation function (average or put normally)
623 * the motion vectors are taken from s->mv and the MV type from s->mv_type
625 static av_always_inline
void MPV_motion_internal(MpegEncContext
*s
,
626 uint8_t *dest_y
, uint8_t *dest_cb
,
627 uint8_t *dest_cr
, int dir
,
628 uint8_t **ref_picture
,
629 op_pixels_func (*pix_op
)[4],
630 qpel_mc_func (*qpix_op
)[16], int is_mpeg12
)
632 int dxy
, mx
, my
, src_x
, src_y
, motion_x
, motion_y
;
639 prefetch_motion(s
, ref_picture
, dir
);
641 if(!is_mpeg12
&& s
->obmc
&& s
->pict_type
!= AV_PICTURE_TYPE_B
){
642 LOCAL_ALIGNED_8(int16_t, mv_cache
, [4], [4][2]);
643 Picture
*cur_frame
= &s
->current_picture
;
644 const int xy
= s
->mb_x
+ s
->mb_y
*s
->mb_stride
;
645 const int mot_stride
= s
->b8_stride
;
646 const int mot_xy
= mb_x
*2 + mb_y
*2*mot_stride
;
648 assert(!s
->mb_skipped
);
650 AV_COPY32(mv_cache
[1][1], cur_frame
->motion_val
[0][mot_xy
]);
651 AV_COPY32(mv_cache
[1][2], cur_frame
->motion_val
[0][mot_xy
+ 1]);
653 AV_COPY32(mv_cache
[2][1], cur_frame
->motion_val
[0][mot_xy
+ mot_stride
]);
654 AV_COPY32(mv_cache
[2][2], cur_frame
->motion_val
[0][mot_xy
+ mot_stride
+ 1]);
656 AV_COPY32(mv_cache
[3][1], cur_frame
->motion_val
[0][mot_xy
+ mot_stride
]);
657 AV_COPY32(mv_cache
[3][2], cur_frame
->motion_val
[0][mot_xy
+ mot_stride
+ 1]);
659 if (mb_y
== 0 || IS_INTRA(cur_frame
->mb_type
[xy
- s
->mb_stride
])) {
660 AV_COPY32(mv_cache
[0][1], mv_cache
[1][1]);
661 AV_COPY32(mv_cache
[0][2], mv_cache
[1][2]);
663 AV_COPY32(mv_cache
[0][1], cur_frame
->motion_val
[0][mot_xy
- mot_stride
]);
664 AV_COPY32(mv_cache
[0][2], cur_frame
->motion_val
[0][mot_xy
- mot_stride
+ 1]);
667 if (mb_x
== 0 || IS_INTRA(cur_frame
->mb_type
[xy
- 1])) {
668 AV_COPY32(mv_cache
[1][0], mv_cache
[1][1]);
669 AV_COPY32(mv_cache
[2][0], mv_cache
[2][1]);
671 AV_COPY32(mv_cache
[1][0], cur_frame
->motion_val
[0][mot_xy
- 1]);
672 AV_COPY32(mv_cache
[2][0], cur_frame
->motion_val
[0][mot_xy
- 1 + mot_stride
]);
675 if (mb_x
+ 1 >= s
->mb_width
|| IS_INTRA(cur_frame
->mb_type
[xy
+ 1])) {
676 AV_COPY32(mv_cache
[1][3], mv_cache
[1][2]);
677 AV_COPY32(mv_cache
[2][3], mv_cache
[2][2]);
679 AV_COPY32(mv_cache
[1][3], cur_frame
->motion_val
[0][mot_xy
+ 2]);
680 AV_COPY32(mv_cache
[2][3], cur_frame
->motion_val
[0][mot_xy
+ 2 + mot_stride
]);
686 const int x
= (i
&1)+1;
687 const int y
= (i
>>1)+1;
689 {mv_cache
[y
][x
][0], mv_cache
[y
][x
][1]},
690 {mv_cache
[y
-1][x
][0], mv_cache
[y
-1][x
][1]},
691 {mv_cache
[y
][x
-1][0], mv_cache
[y
][x
-1][1]},
692 {mv_cache
[y
][x
+1][0], mv_cache
[y
][x
+1][1]},
693 {mv_cache
[y
+1][x
][0], mv_cache
[y
+1][x
][1]}};
695 obmc_motion(s
, dest_y
+ ((i
& 1) * 8) + (i
>> 1) * 8 * s
->linesize
,
697 mb_x
* 16 + (i
& 1) * 8, mb_y
* 16 + (i
>>1) * 8,
704 if(!CONFIG_GRAY
|| !(s
->flags
&CODEC_FLAG_GRAY
))
705 chroma_4mv_motion(s
, dest_cb
, dest_cr
, ref_picture
, pix_op
[1], mx
, my
);
713 if(s
->real_sprite_warping_points
==1){
714 gmc1_motion(s
, dest_y
, dest_cb
, dest_cr
,
717 gmc_motion(s
, dest_y
, dest_cb
, dest_cr
,
720 }else if(!is_mpeg12
&& s
->quarter_sample
){
721 qpel_motion(s
, dest_y
, dest_cb
, dest_cr
,
723 ref_picture
, pix_op
, qpix_op
,
724 s
->mv
[dir
][0][0], s
->mv
[dir
][0][1], 16);
725 } else if (!is_mpeg12
&& (CONFIG_WMV2_DECODER
|| CONFIG_WMV2_ENCODER
) &&
726 s
->mspel
&& s
->codec_id
== AV_CODEC_ID_WMV2
) {
727 ff_mspel_motion(s
, dest_y
, dest_cb
, dest_cr
,
729 s
->mv
[dir
][0][0], s
->mv
[dir
][0][1], 16);
732 mpeg_motion(s
, dest_y
, dest_cb
, dest_cr
, 0,
734 s
->mv
[dir
][0][0], s
->mv
[dir
][0][1], 16, mb_y
);
741 if(s
->quarter_sample
){
743 motion_x
= s
->mv
[dir
][i
][0];
744 motion_y
= s
->mv
[dir
][i
][1];
746 dxy
= ((motion_y
& 3) << 2) | (motion_x
& 3);
747 src_x
= mb_x
* 16 + (motion_x
>> 2) + (i
& 1) * 8;
748 src_y
= mb_y
* 16 + (motion_y
>> 2) + (i
>>1) * 8;
750 /* WARNING: do no forget half pels */
751 src_x
= av_clip(src_x
, -16, s
->width
);
752 if (src_x
== s
->width
)
754 src_y
= av_clip(src_y
, -16, s
->height
);
755 if (src_y
== s
->height
)
758 ptr
= ref_picture
[0] + (src_y
* s
->linesize
) + (src_x
);
759 if(s
->flags
&CODEC_FLAG_EMU_EDGE
){
760 if( (unsigned)src_x
> FFMAX(s
->h_edge_pos
- (motion_x
&3) - 8, 0)
761 || (unsigned)src_y
> FFMAX(s
->v_edge_pos
- (motion_y
&3) - 8, 0)){
762 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
,
765 s
->h_edge_pos
, s
->v_edge_pos
);
766 ptr
= s
->edge_emu_buffer
;
769 dest
= dest_y
+ ((i
& 1) * 8) + (i
>> 1) * 8 * s
->linesize
;
770 qpix_op
[1][dxy
](dest
, ptr
, s
->linesize
);
772 mx
+= s
->mv
[dir
][i
][0]/2;
773 my
+= s
->mv
[dir
][i
][1]/2;
777 hpel_motion(s
, dest_y
+ ((i
& 1) * 8) + (i
>> 1) * 8 * s
->linesize
,
779 mb_x
* 16 + (i
& 1) * 8, mb_y
* 16 + (i
>>1) * 8,
781 s
->mv
[dir
][i
][0], s
->mv
[dir
][i
][1]);
783 mx
+= s
->mv
[dir
][i
][0];
784 my
+= s
->mv
[dir
][i
][1];
788 if(!CONFIG_GRAY
|| !(s
->flags
&CODEC_FLAG_GRAY
))
789 chroma_4mv_motion(s
, dest_cb
, dest_cr
, ref_picture
, pix_op
[1], mx
, my
);
793 if (s
->picture_structure
== PICT_FRAME
) {
794 if(!is_mpeg12
&& s
->quarter_sample
){
796 qpel_motion(s
, dest_y
, dest_cb
, dest_cr
,
797 1, i
, s
->field_select
[dir
][i
],
798 ref_picture
, pix_op
, qpix_op
,
799 s
->mv
[dir
][i
][0], s
->mv
[dir
][i
][1], 8);
803 mpeg_motion_field(s
, dest_y
, dest_cb
, dest_cr
,
804 0, s
->field_select
[dir
][0],
806 s
->mv
[dir
][0][0], s
->mv
[dir
][0][1], 8, mb_y
);
808 mpeg_motion_field(s
, dest_y
, dest_cb
, dest_cr
,
809 1, s
->field_select
[dir
][1],
811 s
->mv
[dir
][1][0], s
->mv
[dir
][1][1], 8, mb_y
);
814 if(s
->picture_structure
!= s
->field_select
[dir
][0] + 1 && s
->pict_type
!= AV_PICTURE_TYPE_B
&& !s
->first_field
){
815 ref_picture
= s
->current_picture_ptr
->f
.data
;
818 mpeg_motion(s
, dest_y
, dest_cb
, dest_cr
,
819 s
->field_select
[dir
][0],
821 s
->mv
[dir
][0][0], s
->mv
[dir
][0][1], 16, mb_y
>>1);
826 uint8_t ** ref2picture
;
828 if(s
->picture_structure
== s
->field_select
[dir
][i
] + 1
829 || s
->pict_type
== AV_PICTURE_TYPE_B
|| s
->first_field
){
830 ref2picture
= ref_picture
;
832 ref2picture
= s
->current_picture_ptr
->f
.data
;
835 mpeg_motion(s
, dest_y
, dest_cb
, dest_cr
,
836 s
->field_select
[dir
][i
],
838 s
->mv
[dir
][i
][0], s
->mv
[dir
][i
][1] + 16*i
, 8, mb_y
>>1);
840 dest_y
+= 16*s
->linesize
;
841 dest_cb
+= (16>>s
->chroma_y_shift
)*s
->uvlinesize
;
842 dest_cr
+= (16>>s
->chroma_y_shift
)*s
->uvlinesize
;
846 if(s
->picture_structure
== PICT_FRAME
){
850 mpeg_motion_field(s
, dest_y
, dest_cb
, dest_cr
,
851 j
, j
^i
, ref_picture
, pix_op
,
852 s
->mv
[dir
][2*i
+ j
][0],
853 s
->mv
[dir
][2*i
+ j
][1], 8, mb_y
);
855 pix_op
= s
->dsp
.avg_pixels_tab
;
859 mpeg_motion(s
, dest_y
, dest_cb
, dest_cr
,
860 s
->picture_structure
!= i
+1,
862 s
->mv
[dir
][2*i
][0],s
->mv
[dir
][2*i
][1],16, mb_y
>>1);
864 // after put we make avg of the same block
865 pix_op
=s
->dsp
.avg_pixels_tab
;
867 //opposite parity is always in the same frame if this is second field
869 ref_picture
= s
->current_picture_ptr
->f
.data
;
878 void ff_MPV_motion(MpegEncContext
*s
,
879 uint8_t *dest_y
, uint8_t *dest_cb
,
880 uint8_t *dest_cr
, int dir
,
881 uint8_t **ref_picture
,
882 op_pixels_func (*pix_op
)[4],
883 qpel_mc_func (*qpix_op
)[16])
886 if(s
->out_format
== FMT_MPEG1
)
887 MPV_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, dir
,
888 ref_picture
, pix_op
, qpix_op
, 1);
891 MPV_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, dir
,
892 ref_picture
, pix_op
, qpix_op
, 0);