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 FFmpeg.
9 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "libavutil/avassert.h"
27 #include "libavutil/internal.h"
30 #include "mpegutils.h"
31 #include "mpegvideo.h"
37 static void gmc1_motion(MpegEncContext
*s
,
38 uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
,
39 uint8_t **ref_picture
)
42 int src_x
, src_y
, motion_x
, motion_y
;
43 ptrdiff_t offset
, linesize
, uvlinesize
;
46 motion_x
= s
->sprite_offset
[0][0];
47 motion_y
= s
->sprite_offset
[0][1];
48 src_x
= s
->mb_x
* 16 + (motion_x
>> (s
->sprite_warping_accuracy
+ 1));
49 src_y
= s
->mb_y
* 16 + (motion_y
>> (s
->sprite_warping_accuracy
+ 1));
50 motion_x
<<= (3 - s
->sprite_warping_accuracy
);
51 motion_y
<<= (3 - s
->sprite_warping_accuracy
);
52 src_x
= av_clip(src_x
, -16, s
->width
);
53 if (src_x
== s
->width
)
55 src_y
= av_clip(src_y
, -16, s
->height
);
56 if (src_y
== s
->height
)
59 linesize
= s
->linesize
;
60 uvlinesize
= s
->uvlinesize
;
62 ptr
= ref_picture
[0] + src_y
* linesize
+ src_x
;
64 if ((unsigned)src_x
>= FFMAX(s
->h_edge_pos
- 17, 0) ||
65 (unsigned)src_y
>= FFMAX(s
->v_edge_pos
- 17, 0)) {
66 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
,
70 s
->h_edge_pos
, s
->v_edge_pos
);
71 ptr
= s
->edge_emu_buffer
;
74 if ((motion_x
| motion_y
) & 7) {
75 s
->mdsp
.gmc1(dest_y
, ptr
, linesize
, 16,
76 motion_x
& 15, motion_y
& 15, 128 - s
->no_rounding
);
77 s
->mdsp
.gmc1(dest_y
+ 8, ptr
+ 8, linesize
, 16,
78 motion_x
& 15, motion_y
& 15, 128 - s
->no_rounding
);
82 dxy
= ((motion_x
>> 3) & 1) | ((motion_y
>> 2) & 2);
84 s
->hdsp
.put_no_rnd_pixels_tab
[0][dxy
](dest_y
, ptr
, linesize
, 16);
86 s
->hdsp
.put_pixels_tab
[0][dxy
](dest_y
, ptr
, linesize
, 16);
90 if (CONFIG_GRAY
&& s
->flags
& CODEC_FLAG_GRAY
)
93 motion_x
= s
->sprite_offset
[1][0];
94 motion_y
= s
->sprite_offset
[1][1];
95 src_x
= s
->mb_x
* 8 + (motion_x
>> (s
->sprite_warping_accuracy
+ 1));
96 src_y
= s
->mb_y
* 8 + (motion_y
>> (s
->sprite_warping_accuracy
+ 1));
97 motion_x
<<= (3 - s
->sprite_warping_accuracy
);
98 motion_y
<<= (3 - s
->sprite_warping_accuracy
);
99 src_x
= av_clip(src_x
, -8, s
->width
>> 1);
100 if (src_x
== s
->width
>> 1)
102 src_y
= av_clip(src_y
, -8, s
->height
>> 1);
103 if (src_y
== s
->height
>> 1)
106 offset
= (src_y
* uvlinesize
) + src_x
;
107 ptr
= ref_picture
[1] + offset
;
108 if ((unsigned)src_x
>= FFMAX((s
->h_edge_pos
>> 1) - 9, 0) ||
109 (unsigned)src_y
>= FFMAX((s
->v_edge_pos
>> 1) - 9, 0)) {
110 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
,
111 uvlinesize
, uvlinesize
,
114 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
115 ptr
= s
->edge_emu_buffer
;
118 s
->mdsp
.gmc1(dest_cb
, ptr
, uvlinesize
, 8,
119 motion_x
& 15, motion_y
& 15, 128 - s
->no_rounding
);
121 ptr
= ref_picture
[2] + offset
;
123 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
,
124 uvlinesize
, uvlinesize
,
127 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
128 ptr
= s
->edge_emu_buffer
;
130 s
->mdsp
.gmc1(dest_cr
, ptr
, uvlinesize
, 8,
131 motion_x
& 15, motion_y
& 15, 128 - s
->no_rounding
);
134 static void gmc_motion(MpegEncContext
*s
,
135 uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
,
136 uint8_t **ref_picture
)
139 int linesize
, uvlinesize
;
140 const int a
= s
->sprite_warping_accuracy
;
143 linesize
= s
->linesize
;
144 uvlinesize
= s
->uvlinesize
;
146 ptr
= ref_picture
[0];
148 ox
= s
->sprite_offset
[0][0] + s
->sprite_delta
[0][0] * s
->mb_x
* 16 +
149 s
->sprite_delta
[0][1] * s
->mb_y
* 16;
150 oy
= s
->sprite_offset
[0][1] + s
->sprite_delta
[1][0] * s
->mb_x
* 16 +
151 s
->sprite_delta
[1][1] * s
->mb_y
* 16;
153 s
->mdsp
.gmc(dest_y
, ptr
, linesize
, 16,
155 s
->sprite_delta
[0][0], s
->sprite_delta
[0][1],
156 s
->sprite_delta
[1][0], s
->sprite_delta
[1][1],
157 a
+ 1, (1 << (2 * a
+ 1)) - s
->no_rounding
,
158 s
->h_edge_pos
, s
->v_edge_pos
);
159 s
->mdsp
.gmc(dest_y
+ 8, ptr
, linesize
, 16,
160 ox
+ s
->sprite_delta
[0][0] * 8,
161 oy
+ s
->sprite_delta
[1][0] * 8,
162 s
->sprite_delta
[0][0], s
->sprite_delta
[0][1],
163 s
->sprite_delta
[1][0], s
->sprite_delta
[1][1],
164 a
+ 1, (1 << (2 * a
+ 1)) - s
->no_rounding
,
165 s
->h_edge_pos
, s
->v_edge_pos
);
167 if (CONFIG_GRAY
&& s
->flags
& CODEC_FLAG_GRAY
)
170 ox
= s
->sprite_offset
[1][0] + s
->sprite_delta
[0][0] * s
->mb_x
* 8 +
171 s
->sprite_delta
[0][1] * s
->mb_y
* 8;
172 oy
= s
->sprite_offset
[1][1] + s
->sprite_delta
[1][0] * s
->mb_x
* 8 +
173 s
->sprite_delta
[1][1] * s
->mb_y
* 8;
175 ptr
= ref_picture
[1];
176 s
->mdsp
.gmc(dest_cb
, ptr
, uvlinesize
, 8,
178 s
->sprite_delta
[0][0], s
->sprite_delta
[0][1],
179 s
->sprite_delta
[1][0], s
->sprite_delta
[1][1],
180 a
+ 1, (1 << (2 * a
+ 1)) - s
->no_rounding
,
181 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
183 ptr
= ref_picture
[2];
184 s
->mdsp
.gmc(dest_cr
, ptr
, uvlinesize
, 8,
186 s
->sprite_delta
[0][0], s
->sprite_delta
[0][1],
187 s
->sprite_delta
[1][0], s
->sprite_delta
[1][1],
188 a
+ 1, (1 << (2 * a
+ 1)) - s
->no_rounding
,
189 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
192 static inline int hpel_motion(MpegEncContext
*s
,
193 uint8_t *dest
, uint8_t *src
,
194 int src_x
, int src_y
,
195 op_pixels_func
*pix_op
,
196 int motion_x
, int motion_y
)
201 src_x
+= motion_x
>> 1;
202 src_y
+= motion_y
>> 1;
204 /* WARNING: do no forget half pels */
205 src_x
= av_clip(src_x
, -16, s
->width
); // FIXME unneeded for emu?
206 if (src_x
!= s
->width
)
208 src_y
= av_clip(src_y
, -16, s
->height
);
209 if (src_y
!= s
->height
)
210 dxy
|= (motion_y
& 1) << 1;
211 src
+= src_y
* s
->linesize
+ src_x
;
213 if ((unsigned)src_x
> FFMAX(s
->h_edge_pos
- (motion_x
& 1) - 8, 0) ||
214 (unsigned)src_y
> FFMAX(s
->v_edge_pos
- (motion_y
& 1) - 8, 0)) {
215 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, src
,
216 s
->linesize
, s
->linesize
,
219 s
->h_edge_pos
, s
->v_edge_pos
);
220 src
= s
->edge_emu_buffer
;
223 pix_op
[dxy
](dest
, src
, s
->linesize
, 8);
227 static av_always_inline
228 void mpeg_motion_internal(MpegEncContext
*s
,
235 uint8_t **ref_picture
,
236 op_pixels_func (*pix_op
)[4],
243 uint8_t *ptr_y
, *ptr_cb
, *ptr_cr
;
244 int dxy
, uvdxy
, mx
, my
, src_x
, src_y
,
245 uvsrc_x
, uvsrc_y
, v_edge_pos
;
246 ptrdiff_t uvlinesize
, linesize
;
249 if (s
->quarter_sample
) {
255 v_edge_pos
= s
->v_edge_pos
>> field_based
;
256 linesize
= s
->current_picture
.f
->linesize
[0] << field_based
;
257 uvlinesize
= s
->current_picture
.f
->linesize
[1] << field_based
;
259 dxy
= ((motion_y
& 1) << 1) | (motion_x
& 1);
260 src_x
= s
->mb_x
* 16 + (motion_x
>> 1);
261 src_y
= (mb_y
<< (4 - field_based
)) + (motion_y
>> 1);
263 if (!is_mpeg12
&& s
->out_format
== FMT_H263
) {
264 if ((s
->workaround_bugs
& FF_BUG_HPEL_CHROMA
) && field_based
) {
265 mx
= (motion_x
>> 1) | (motion_x
& 1);
267 uvdxy
= ((my
& 1) << 1) | (mx
& 1);
268 uvsrc_x
= s
->mb_x
* 8 + (mx
>> 1);
269 uvsrc_y
= (mb_y
<< (3 - field_based
)) + (my
>> 1);
271 uvdxy
= dxy
| (motion_y
& 2) | ((motion_x
& 2) >> 1);
272 uvsrc_x
= src_x
>> 1;
273 uvsrc_y
= src_y
>> 1;
275 // Even chroma mv's are full pel in H261
276 } else if (!is_mpeg12
&& s
->out_format
== FMT_H261
) {
280 uvsrc_x
= s
->mb_x
* 8 + mx
;
281 uvsrc_y
= mb_y
* 8 + my
;
283 if (s
->chroma_y_shift
) {
286 uvdxy
= ((my
& 1) << 1) | (mx
& 1);
287 uvsrc_x
= s
->mb_x
* 8 + (mx
>> 1);
288 uvsrc_y
= (mb_y
<< (3 - field_based
)) + (my
>> 1);
290 if (s
->chroma_x_shift
) {
293 uvdxy
= ((motion_y
& 1) << 1) | (mx
& 1);
294 uvsrc_x
= s
->mb_x
* 8 + (mx
>> 1);
305 ptr_y
= ref_picture
[0] + src_y
* linesize
+ src_x
;
306 ptr_cb
= ref_picture
[1] + uvsrc_y
* uvlinesize
+ uvsrc_x
;
307 ptr_cr
= ref_picture
[2] + uvsrc_y
* uvlinesize
+ uvsrc_x
;
309 if ((unsigned)src_x
> FFMAX(s
->h_edge_pos
- (motion_x
& 1) - 16, 0) ||
310 (unsigned)src_y
> FFMAX( v_edge_pos
- (motion_y
& 1) - h
, 0)) {
312 s
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
||
313 s
->codec_id
== AV_CODEC_ID_MPEG1VIDEO
) {
314 av_log(s
->avctx
, AV_LOG_DEBUG
,
315 "MPEG motion vector out of boundary (%d %d)\n", src_x
,
319 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr_y
,
320 s
->linesize
, s
->linesize
,
321 17, 17 + field_based
,
322 src_x
, src_y
<< field_based
,
323 s
->h_edge_pos
, s
->v_edge_pos
);
324 ptr_y
= s
->edge_emu_buffer
;
325 if (!CONFIG_GRAY
|| !(s
->flags
& CODEC_FLAG_GRAY
)) {
326 uint8_t *ubuf
= s
->edge_emu_buffer
+ 18 * s
->linesize
;
327 uint8_t *vbuf
= ubuf
+ 9 * s
->uvlinesize
;
328 s
->vdsp
.emulated_edge_mc(ubuf
, ptr_cb
,
329 s
->uvlinesize
, s
->uvlinesize
,
331 uvsrc_x
, uvsrc_y
<< field_based
,
332 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
333 s
->vdsp
.emulated_edge_mc(vbuf
, ptr_cr
,
334 s
->uvlinesize
, s
->uvlinesize
,
336 uvsrc_x
, uvsrc_y
<< field_based
,
337 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
343 /* FIXME use this for field pix too instead of the obnoxious hack which
344 * changes picture.data */
346 dest_y
+= s
->linesize
;
347 dest_cb
+= s
->uvlinesize
;
348 dest_cr
+= s
->uvlinesize
;
352 ptr_y
+= s
->linesize
;
353 ptr_cb
+= s
->uvlinesize
;
354 ptr_cr
+= s
->uvlinesize
;
357 pix_op
[0][dxy
](dest_y
, ptr_y
, linesize
, h
);
359 if (!CONFIG_GRAY
|| !(s
->flags
& CODEC_FLAG_GRAY
)) {
360 pix_op
[s
->chroma_x_shift
][uvdxy
]
361 (dest_cb
, ptr_cb
, uvlinesize
, h
>> s
->chroma_y_shift
);
362 pix_op
[s
->chroma_x_shift
][uvdxy
]
363 (dest_cr
, ptr_cr
, uvlinesize
, h
>> s
->chroma_y_shift
);
365 if (!is_mpeg12
&& (CONFIG_H261_ENCODER
|| CONFIG_H261_DECODER
) &&
366 s
->out_format
== FMT_H261
) {
367 ff_h261_loop_filter(s
);
370 /* apply one mpeg motion vector to the three components */
371 static void mpeg_motion(MpegEncContext
*s
,
372 uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
,
373 int field_select
, uint8_t **ref_picture
,
374 op_pixels_func (*pix_op
)[4],
375 int motion_x
, int motion_y
, int h
, int mb_y
)
378 if (s
->out_format
== FMT_MPEG1
)
379 mpeg_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, 0, 0,
380 field_select
, ref_picture
, pix_op
,
381 motion_x
, motion_y
, h
, 1, mb_y
);
384 mpeg_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, 0, 0,
385 field_select
, ref_picture
, pix_op
,
386 motion_x
, motion_y
, h
, 0, mb_y
);
389 static void mpeg_motion_field(MpegEncContext
*s
, uint8_t *dest_y
,
390 uint8_t *dest_cb
, uint8_t *dest_cr
,
391 int bottom_field
, int field_select
,
392 uint8_t **ref_picture
,
393 op_pixels_func (*pix_op
)[4],
394 int motion_x
, int motion_y
, int h
, int mb_y
)
397 if (s
->out_format
== FMT_MPEG1
)
398 mpeg_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, 1,
399 bottom_field
, field_select
, ref_picture
, pix_op
,
400 motion_x
, motion_y
, h
, 1, mb_y
);
403 mpeg_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, 1,
404 bottom_field
, field_select
, ref_picture
, pix_op
,
405 motion_x
, motion_y
, h
, 0, mb_y
);
408 // FIXME: SIMDify, avg variant, 16x16 version
409 static inline void put_obmc(uint8_t *dst
, uint8_t *src
[5], int stride
)
412 uint8_t *const top
= src
[1];
413 uint8_t *const left
= src
[2];
414 uint8_t *const mid
= src
[0];
415 uint8_t *const right
= src
[3];
416 uint8_t *const bottom
= src
[4];
417 #define OBMC_FILTER(x, t, l, m, r, b)\
418 dst[x]= (t*top[x] + l*left[x] + m*mid[x] + r*right[x] + b*bottom[x] + 4)>>3
419 #define OBMC_FILTER4(x, t, l, m, r, b)\
420 OBMC_FILTER(x , t, l, m, r, b);\
421 OBMC_FILTER(x+1 , t, l, m, r, b);\
422 OBMC_FILTER(x +stride, t, l, m, r, b);\
423 OBMC_FILTER(x+1+stride, t, l, m, r, b);
426 OBMC_FILTER (x
, 2, 2, 4, 0, 0);
427 OBMC_FILTER (x
+ 1, 2, 1, 5, 0, 0);
428 OBMC_FILTER4(x
+ 2, 2, 1, 5, 0, 0);
429 OBMC_FILTER4(x
+ 4, 2, 0, 5, 1, 0);
430 OBMC_FILTER (x
+ 6, 2, 0, 5, 1, 0);
431 OBMC_FILTER (x
+ 7, 2, 0, 4, 2, 0);
433 OBMC_FILTER (x
, 1, 2, 5, 0, 0);
434 OBMC_FILTER (x
+ 1, 1, 2, 5, 0, 0);
435 OBMC_FILTER (x
+ 6, 1, 0, 5, 2, 0);
436 OBMC_FILTER (x
+ 7, 1, 0, 5, 2, 0);
438 OBMC_FILTER4(x
, 1, 2, 5, 0, 0);
439 OBMC_FILTER4(x
+ 2, 1, 1, 6, 0, 0);
440 OBMC_FILTER4(x
+ 4, 1, 0, 6, 1, 0);
441 OBMC_FILTER4(x
+ 6, 1, 0, 5, 2, 0);
443 OBMC_FILTER4(x
, 0, 2, 5, 0, 1);
444 OBMC_FILTER4(x
+ 2, 0, 1, 6, 0, 1);
445 OBMC_FILTER4(x
+ 4, 0, 0, 6, 1, 1);
446 OBMC_FILTER4(x
+ 6, 0, 0, 5, 2, 1);
448 OBMC_FILTER (x
, 0, 2, 5, 0, 1);
449 OBMC_FILTER (x
+ 1, 0, 2, 5, 0, 1);
450 OBMC_FILTER4(x
+ 2, 0, 1, 5, 0, 2);
451 OBMC_FILTER4(x
+ 4, 0, 0, 5, 1, 2);
452 OBMC_FILTER (x
+ 6, 0, 0, 5, 2, 1);
453 OBMC_FILTER (x
+ 7, 0, 0, 5, 2, 1);
455 OBMC_FILTER (x
, 0, 2, 4, 0, 2);
456 OBMC_FILTER (x
+ 1, 0, 1, 5, 0, 2);
457 OBMC_FILTER (x
+ 6, 0, 0, 5, 1, 2);
458 OBMC_FILTER (x
+ 7, 0, 0, 4, 2, 2);
461 /* obmc for 1 8x8 luma block */
462 static inline void obmc_motion(MpegEncContext
*s
,
463 uint8_t *dest
, uint8_t *src
,
464 int src_x
, int src_y
,
465 op_pixels_func
*pix_op
,
466 int16_t mv
[5][2] /* mid top left right bottom */)
472 av_assert2(s
->quarter_sample
== 0);
474 for (i
= 0; i
< 5; i
++) {
475 if (i
&& mv
[i
][0] == mv
[MID
][0] && mv
[i
][1] == mv
[MID
][1]) {
478 ptr
[i
] = s
->obmc_scratchpad
+ 8 * (i
& 1) +
479 s
->linesize
* 8 * (i
>> 1);
480 hpel_motion(s
, ptr
[i
], src
, src_x
, src_y
, pix_op
,
485 put_obmc(dest
, ptr
, s
->linesize
);
488 static inline void qpel_motion(MpegEncContext
*s
,
492 int field_based
, int bottom_field
,
493 int field_select
, uint8_t **ref_picture
,
494 op_pixels_func (*pix_op
)[4],
495 qpel_mc_func (*qpix_op
)[16],
496 int motion_x
, int motion_y
, int h
)
498 uint8_t *ptr_y
, *ptr_cb
, *ptr_cr
;
499 int dxy
, uvdxy
, mx
, my
, src_x
, src_y
, uvsrc_x
, uvsrc_y
, v_edge_pos
;
500 ptrdiff_t linesize
, uvlinesize
;
502 dxy
= ((motion_y
& 3) << 2) | (motion_x
& 3);
504 src_x
= s
->mb_x
* 16 + (motion_x
>> 2);
505 src_y
= s
->mb_y
* (16 >> field_based
) + (motion_y
>> 2);
507 v_edge_pos
= s
->v_edge_pos
>> field_based
;
508 linesize
= s
->linesize
<< field_based
;
509 uvlinesize
= s
->uvlinesize
<< field_based
;
514 } else if (s
->workaround_bugs
& FF_BUG_QPEL_CHROMA2
) {
515 static const int rtab
[8] = { 0, 0, 1, 1, 0, 0, 0, 1 };
516 mx
= (motion_x
>> 1) + rtab
[motion_x
& 7];
517 my
= (motion_y
>> 1) + rtab
[motion_y
& 7];
518 } else if (s
->workaround_bugs
& FF_BUG_QPEL_CHROMA
) {
519 mx
= (motion_x
>> 1) | (motion_x
& 1);
520 my
= (motion_y
>> 1) | (motion_y
& 1);
525 mx
= (mx
>> 1) | (mx
& 1);
526 my
= (my
>> 1) | (my
& 1);
528 uvdxy
= (mx
& 1) | ((my
& 1) << 1);
532 uvsrc_x
= s
->mb_x
* 8 + mx
;
533 uvsrc_y
= s
->mb_y
* (8 >> field_based
) + my
;
535 ptr_y
= ref_picture
[0] + src_y
* linesize
+ src_x
;
536 ptr_cb
= ref_picture
[1] + uvsrc_y
* uvlinesize
+ uvsrc_x
;
537 ptr_cr
= ref_picture
[2] + uvsrc_y
* uvlinesize
+ uvsrc_x
;
539 if ((unsigned)src_x
> FFMAX(s
->h_edge_pos
- (motion_x
& 3) - 16, 0) ||
540 (unsigned)src_y
> FFMAX( v_edge_pos
- (motion_y
& 3) - h
, 0)) {
541 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr_y
,
542 s
->linesize
, s
->linesize
,
543 17, 17 + field_based
,
544 src_x
, src_y
<< field_based
,
545 s
->h_edge_pos
, s
->v_edge_pos
);
546 ptr_y
= s
->edge_emu_buffer
;
547 if (!CONFIG_GRAY
|| !(s
->flags
& CODEC_FLAG_GRAY
)) {
548 uint8_t *ubuf
= s
->edge_emu_buffer
+ 18 * s
->linesize
;
549 uint8_t *vbuf
= ubuf
+ 9 * s
->uvlinesize
;
550 s
->vdsp
.emulated_edge_mc(ubuf
, ptr_cb
,
551 s
->uvlinesize
, s
->uvlinesize
,
553 uvsrc_x
, uvsrc_y
<< field_based
,
554 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
555 s
->vdsp
.emulated_edge_mc(vbuf
, ptr_cr
,
556 s
->uvlinesize
, s
->uvlinesize
,
558 uvsrc_x
, uvsrc_y
<< field_based
,
559 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
566 qpix_op
[0][dxy
](dest_y
, ptr_y
, linesize
);
569 dest_y
+= s
->linesize
;
570 dest_cb
+= s
->uvlinesize
;
571 dest_cr
+= s
->uvlinesize
;
575 ptr_y
+= s
->linesize
;
576 ptr_cb
+= s
->uvlinesize
;
577 ptr_cr
+= s
->uvlinesize
;
579 // damn interlaced mode
580 // FIXME boundary mirroring is not exactly correct here
581 qpix_op
[1][dxy
](dest_y
, ptr_y
, linesize
);
582 qpix_op
[1][dxy
](dest_y
+ 8, ptr_y
+ 8, linesize
);
584 if (!CONFIG_GRAY
|| !(s
->flags
& CODEC_FLAG_GRAY
)) {
585 pix_op
[1][uvdxy
](dest_cr
, ptr_cr
, uvlinesize
, h
>> 1);
586 pix_op
[1][uvdxy
](dest_cb
, ptr_cb
, uvlinesize
, h
>> 1);
591 * h263 chroma 4mv motion compensation.
593 static void chroma_4mv_motion(MpegEncContext
*s
,
594 uint8_t *dest_cb
, uint8_t *dest_cr
,
595 uint8_t **ref_picture
,
596 op_pixels_func
*pix_op
,
600 int src_x
, src_y
, dxy
, emu
= 0;
603 /* In case of 8X8, we construct a single chroma motion vector
604 * with a special rounding */
605 mx
= ff_h263_round_chroma(mx
);
606 my
= ff_h263_round_chroma(my
);
608 dxy
= ((my
& 1) << 1) | (mx
& 1);
612 src_x
= s
->mb_x
* 8 + mx
;
613 src_y
= s
->mb_y
* 8 + my
;
614 src_x
= av_clip(src_x
, -8, (s
->width
>> 1));
615 if (src_x
== (s
->width
>> 1))
617 src_y
= av_clip(src_y
, -8, (s
->height
>> 1));
618 if (src_y
== (s
->height
>> 1))
621 offset
= src_y
* s
->uvlinesize
+ src_x
;
622 ptr
= ref_picture
[1] + offset
;
623 if ((unsigned)src_x
> FFMAX((s
->h_edge_pos
>> 1) - (dxy
& 1) - 8, 0) ||
624 (unsigned)src_y
> FFMAX((s
->v_edge_pos
>> 1) - (dxy
>> 1) - 8, 0)) {
625 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
,
626 s
->uvlinesize
, s
->uvlinesize
,
628 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
629 ptr
= s
->edge_emu_buffer
;
632 pix_op
[dxy
](dest_cb
, ptr
, s
->uvlinesize
, 8);
634 ptr
= ref_picture
[2] + offset
;
636 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
,
637 s
->uvlinesize
, s
->uvlinesize
,
639 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
640 ptr
= s
->edge_emu_buffer
;
642 pix_op
[dxy
](dest_cr
, ptr
, s
->uvlinesize
, 8);
645 static inline void prefetch_motion(MpegEncContext
*s
, uint8_t **pix
, int dir
)
647 /* fetch pixels for estimated mv 4 macroblocks ahead
648 * optimized for 64byte cache lines */
649 const int shift
= s
->quarter_sample
? 2 : 1;
650 const int mx
= (s
->mv
[dir
][0][0] >> shift
) + 16 * s
->mb_x
+ 8;
651 const int my
= (s
->mv
[dir
][0][1] >> shift
) + 16 * s
->mb_y
;
652 int off
= mx
+ (my
+ (s
->mb_x
& 3) * 4) * s
->linesize
+ 64;
654 s
->vdsp
.prefetch(pix
[0] + off
, s
->linesize
, 4);
655 off
= (mx
>> 1) + ((my
>> 1) + (s
->mb_x
& 7)) * s
->uvlinesize
+ 64;
656 s
->vdsp
.prefetch(pix
[1] + off
, pix
[2] - pix
[1], 2);
659 static inline void apply_obmc(MpegEncContext
*s
,
663 uint8_t **ref_picture
,
664 op_pixels_func (*pix_op
)[4])
666 LOCAL_ALIGNED_8(int16_t, mv_cache
, [4], [4][2]);
667 Picture
*cur_frame
= &s
->current_picture
;
670 const int xy
= mb_x
+ mb_y
* s
->mb_stride
;
671 const int mot_stride
= s
->b8_stride
;
672 const int mot_xy
= mb_x
* 2 + mb_y
* 2 * mot_stride
;
675 av_assert2(!s
->mb_skipped
);
677 AV_COPY32(mv_cache
[1][1], cur_frame
->motion_val
[0][mot_xy
]);
678 AV_COPY32(mv_cache
[1][2], cur_frame
->motion_val
[0][mot_xy
+ 1]);
680 AV_COPY32(mv_cache
[2][1],
681 cur_frame
->motion_val
[0][mot_xy
+ mot_stride
]);
682 AV_COPY32(mv_cache
[2][2],
683 cur_frame
->motion_val
[0][mot_xy
+ mot_stride
+ 1]);
685 AV_COPY32(mv_cache
[3][1],
686 cur_frame
->motion_val
[0][mot_xy
+ mot_stride
]);
687 AV_COPY32(mv_cache
[3][2],
688 cur_frame
->motion_val
[0][mot_xy
+ mot_stride
+ 1]);
690 if (mb_y
== 0 || IS_INTRA(cur_frame
->mb_type
[xy
- s
->mb_stride
])) {
691 AV_COPY32(mv_cache
[0][1], mv_cache
[1][1]);
692 AV_COPY32(mv_cache
[0][2], mv_cache
[1][2]);
694 AV_COPY32(mv_cache
[0][1],
695 cur_frame
->motion_val
[0][mot_xy
- mot_stride
]);
696 AV_COPY32(mv_cache
[0][2],
697 cur_frame
->motion_val
[0][mot_xy
- mot_stride
+ 1]);
700 if (mb_x
== 0 || IS_INTRA(cur_frame
->mb_type
[xy
- 1])) {
701 AV_COPY32(mv_cache
[1][0], mv_cache
[1][1]);
702 AV_COPY32(mv_cache
[2][0], mv_cache
[2][1]);
704 AV_COPY32(mv_cache
[1][0], cur_frame
->motion_val
[0][mot_xy
- 1]);
705 AV_COPY32(mv_cache
[2][0],
706 cur_frame
->motion_val
[0][mot_xy
- 1 + mot_stride
]);
709 if (mb_x
+ 1 >= s
->mb_width
|| IS_INTRA(cur_frame
->mb_type
[xy
+ 1])) {
710 AV_COPY32(mv_cache
[1][3], mv_cache
[1][2]);
711 AV_COPY32(mv_cache
[2][3], mv_cache
[2][2]);
713 AV_COPY32(mv_cache
[1][3], cur_frame
->motion_val
[0][mot_xy
+ 2]);
714 AV_COPY32(mv_cache
[2][3],
715 cur_frame
->motion_val
[0][mot_xy
+ 2 + mot_stride
]);
720 for (i
= 0; i
< 4; i
++) {
721 const int x
= (i
& 1) + 1;
722 const int y
= (i
>> 1) + 1;
724 { mv_cache
[y
][x
][0], mv_cache
[y
][x
][1] },
725 { mv_cache
[y
- 1][x
][0], mv_cache
[y
- 1][x
][1] },
726 { mv_cache
[y
][x
- 1][0], mv_cache
[y
][x
- 1][1] },
727 { mv_cache
[y
][x
+ 1][0], mv_cache
[y
][x
+ 1][1] },
728 { mv_cache
[y
+ 1][x
][0], mv_cache
[y
+ 1][x
][1] }
731 obmc_motion(s
, dest_y
+ ((i
& 1) * 8) + (i
>> 1) * 8 * s
->linesize
,
733 mb_x
* 16 + (i
& 1) * 8, mb_y
* 16 + (i
>> 1) * 8,
740 if (!CONFIG_GRAY
|| !(s
->flags
& CODEC_FLAG_GRAY
))
741 chroma_4mv_motion(s
, dest_cb
, dest_cr
,
742 ref_picture
, pix_op
[1],
746 static inline void apply_8x8(MpegEncContext
*s
,
751 uint8_t **ref_picture
,
752 qpel_mc_func (*qpix_op
)[16],
753 op_pixels_func (*pix_op
)[4])
755 int dxy
, mx
, my
, src_x
, src_y
;
763 if (s
->quarter_sample
) {
764 for (i
= 0; i
< 4; i
++) {
765 int motion_x
= s
->mv
[dir
][i
][0];
766 int motion_y
= s
->mv
[dir
][i
][1];
768 dxy
= ((motion_y
& 3) << 2) | (motion_x
& 3);
769 src_x
= mb_x
* 16 + (motion_x
>> 2) + (i
& 1) * 8;
770 src_y
= mb_y
* 16 + (motion_y
>> 2) + (i
>> 1) * 8;
772 /* WARNING: do no forget half pels */
773 src_x
= av_clip(src_x
, -16, s
->width
);
774 if (src_x
== s
->width
)
776 src_y
= av_clip(src_y
, -16, s
->height
);
777 if (src_y
== s
->height
)
780 ptr
= ref_picture
[0] + (src_y
* s
->linesize
) + (src_x
);
781 if ((unsigned)src_x
> FFMAX(s
->h_edge_pos
- (motion_x
& 3) - 8, 0) ||
782 (unsigned)src_y
> FFMAX(s
->v_edge_pos
- (motion_y
& 3) - 8, 0)) {
783 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
,
784 s
->linesize
, s
->linesize
,
789 ptr
= s
->edge_emu_buffer
;
791 dest
= dest_y
+ ((i
& 1) * 8) + (i
>> 1) * 8 * s
->linesize
;
792 qpix_op
[1][dxy
](dest
, ptr
, s
->linesize
);
794 mx
+= s
->mv
[dir
][i
][0] / 2;
795 my
+= s
->mv
[dir
][i
][1] / 2;
798 for (i
= 0; i
< 4; i
++) {
800 dest_y
+ ((i
& 1) * 8) + (i
>> 1) * 8 * s
->linesize
,
802 mb_x
* 16 + (i
& 1) * 8,
803 mb_y
* 16 + (i
>> 1) * 8,
808 mx
+= s
->mv
[dir
][i
][0];
809 my
+= s
->mv
[dir
][i
][1];
813 if (!CONFIG_GRAY
|| !(s
->flags
& CODEC_FLAG_GRAY
))
814 chroma_4mv_motion(s
, dest_cb
, dest_cr
,
815 ref_picture
, pix_op
[1], mx
, my
);
819 * motion compensation of a single macroblock
821 * @param dest_y luma destination pointer
822 * @param dest_cb chroma cb/u destination pointer
823 * @param dest_cr chroma cr/v destination pointer
824 * @param dir direction (0->forward, 1->backward)
825 * @param ref_picture array[3] of pointers to the 3 planes of the reference picture
826 * @param pix_op halfpel motion compensation function (average or put normally)
827 * @param qpix_op qpel motion compensation function (average or put normally)
828 * the motion vectors are taken from s->mv and the MV type from s->mv_type
830 static av_always_inline
void mpv_motion_internal(MpegEncContext
*s
,
835 uint8_t **ref_picture
,
836 op_pixels_func (*pix_op
)[4],
837 qpel_mc_func (*qpix_op
)[16],
843 prefetch_motion(s
, ref_picture
, dir
);
845 if (!is_mpeg12
&& s
->obmc
&& s
->pict_type
!= AV_PICTURE_TYPE_B
) {
846 apply_obmc(s
, dest_y
, dest_cb
, dest_cr
, ref_picture
, pix_op
);
850 switch (s
->mv_type
) {
853 if (s
->real_sprite_warping_points
== 1) {
854 gmc1_motion(s
, dest_y
, dest_cb
, dest_cr
,
857 gmc_motion(s
, dest_y
, dest_cb
, dest_cr
,
860 } else if (!is_mpeg12
&& s
->quarter_sample
) {
861 qpel_motion(s
, dest_y
, dest_cb
, dest_cr
,
863 ref_picture
, pix_op
, qpix_op
,
864 s
->mv
[dir
][0][0], s
->mv
[dir
][0][1], 16);
865 } else if (!is_mpeg12
&& (CONFIG_WMV2_DECODER
|| CONFIG_WMV2_ENCODER
) &&
866 s
->mspel
&& s
->codec_id
== AV_CODEC_ID_WMV2
) {
867 ff_mspel_motion(s
, dest_y
, dest_cb
, dest_cr
,
869 s
->mv
[dir
][0][0], s
->mv
[dir
][0][1], 16);
871 mpeg_motion(s
, dest_y
, dest_cb
, dest_cr
, 0,
873 s
->mv
[dir
][0][0], s
->mv
[dir
][0][1], 16, mb_y
);
878 apply_8x8(s
, dest_y
, dest_cb
, dest_cr
,
879 dir
, ref_picture
, qpix_op
, pix_op
);
882 if (s
->picture_structure
== PICT_FRAME
) {
883 if (!is_mpeg12
&& s
->quarter_sample
) {
884 for (i
= 0; i
< 2; i
++)
885 qpel_motion(s
, dest_y
, dest_cb
, dest_cr
,
886 1, i
, s
->field_select
[dir
][i
],
887 ref_picture
, pix_op
, qpix_op
,
888 s
->mv
[dir
][i
][0], s
->mv
[dir
][i
][1], 8);
891 mpeg_motion_field(s
, dest_y
, dest_cb
, dest_cr
,
892 0, s
->field_select
[dir
][0],
894 s
->mv
[dir
][0][0], s
->mv
[dir
][0][1], 8, mb_y
);
896 mpeg_motion_field(s
, dest_y
, dest_cb
, dest_cr
,
897 1, s
->field_select
[dir
][1],
899 s
->mv
[dir
][1][0], s
->mv
[dir
][1][1], 8, mb_y
);
902 if ( s
->picture_structure
!= s
->field_select
[dir
][0] + 1 && s
->pict_type
!= AV_PICTURE_TYPE_B
&& !s
->first_field
903 || !ref_picture
[0]) {
904 ref_picture
= s
->current_picture_ptr
->f
->data
;
907 mpeg_motion(s
, dest_y
, dest_cb
, dest_cr
,
908 s
->field_select
[dir
][0],
910 s
->mv
[dir
][0][0], s
->mv
[dir
][0][1], 16, mb_y
>> 1);
914 for (i
= 0; i
< 2; i
++) {
915 uint8_t **ref2picture
;
917 if ((s
->picture_structure
== s
->field_select
[dir
][i
] + 1
918 || s
->pict_type
== AV_PICTURE_TYPE_B
|| s
->first_field
) && ref_picture
[0]) {
919 ref2picture
= ref_picture
;
921 ref2picture
= s
->current_picture_ptr
->f
->data
;
924 mpeg_motion(s
, dest_y
, dest_cb
, dest_cr
,
925 s
->field_select
[dir
][i
],
927 s
->mv
[dir
][i
][0], s
->mv
[dir
][i
][1] + 16 * i
,
930 dest_y
+= 16 * s
->linesize
;
931 dest_cb
+= (16 >> s
->chroma_y_shift
) * s
->uvlinesize
;
932 dest_cr
+= (16 >> s
->chroma_y_shift
) * s
->uvlinesize
;
936 if (s
->picture_structure
== PICT_FRAME
) {
937 for (i
= 0; i
< 2; i
++) {
939 for (j
= 0; j
< 2; j
++)
940 mpeg_motion_field(s
, dest_y
, dest_cb
, dest_cr
,
941 j
, j
^ i
, ref_picture
, pix_op
,
942 s
->mv
[dir
][2 * i
+ j
][0],
943 s
->mv
[dir
][2 * i
+ j
][1], 8, mb_y
);
944 pix_op
= s
->hdsp
.avg_pixels_tab
;
947 if (!ref_picture
[0]) {
948 ref_picture
= s
->current_picture_ptr
->f
->data
;
950 for (i
= 0; i
< 2; i
++) {
951 mpeg_motion(s
, dest_y
, dest_cb
, dest_cr
,
952 s
->picture_structure
!= i
+ 1,
954 s
->mv
[dir
][2 * i
][0], s
->mv
[dir
][2 * i
][1],
957 // after put we make avg of the same block
958 pix_op
= s
->hdsp
.avg_pixels_tab
;
960 /* opposite parity is always in the same frame if this is
962 if (!s
->first_field
) {
963 ref_picture
= s
->current_picture_ptr
->f
->data
;
968 default: av_assert2(0);
972 void ff_mpv_motion(MpegEncContext
*s
,
973 uint8_t *dest_y
, uint8_t *dest_cb
,
974 uint8_t *dest_cr
, int dir
,
975 uint8_t **ref_picture
,
976 op_pixels_func (*pix_op
)[4],
977 qpel_mc_func (*qpix_op
)[16])
980 if (s
->out_format
== FMT_MPEG1
)
981 mpv_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, dir
,
982 ref_picture
, pix_op
, qpix_op
, 1);
985 mpv_motion_internal(s
, dest_y
, dest_cb
, dest_cr
, dir
,
986 ref_picture
, pix_op
, qpix_op
, 0);