2 * Copyright (C) 2003 the ffmpeg project
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * Id RoQ Video common functions based on work by Dr. Tim Ferguson
30 #define avg2(a,b) av_clip_uint8(((int)(a)+(int)(b)+1)>>1)
31 #define avg4(a,b,c,d) av_clip_uint8(((int)(a)+(int)(b)+(int)(c)+(int)(d)+2)>>2)
33 void ff_apply_vector_2x2(RoqContext
*ri
, int x
, int y
, roq_cell
*cell
)
37 yptr
= ri
->current_frame
->data
[0] + (y
* ri
->y_stride
) + x
;
40 yptr
+= (ri
->y_stride
- 2);
43 ri
->current_frame
->data
[1][(y
/2) * (ri
->c_stride
) + x
/2] = cell
->u
;
44 ri
->current_frame
->data
[2][(y
/2) * (ri
->c_stride
) + x
/2] = cell
->v
;
47 void ff_apply_vector_4x4(RoqContext
*ri
, int x
, int y
, roq_cell
*cell
)
49 unsigned long row_inc
, c_row_inc
;
50 register unsigned char y0
, y1
, u
, v
;
51 unsigned char *yptr
, *uptr
, *vptr
;
53 yptr
= ri
->current_frame
->data
[0] + (y
* ri
->y_stride
) + x
;
54 uptr
= ri
->current_frame
->data
[1] + (y
/2) * (ri
->c_stride
) + x
/2;
55 vptr
= ri
->current_frame
->data
[2] + (y
/2) * (ri
->c_stride
) + x
/2;
57 row_inc
= ri
->y_stride
- 4;
58 c_row_inc
= (ri
->c_stride
) - 2;
59 *yptr
++ = y0
= cell
->y
[0]; *uptr
++ = u
= cell
->u
; *vptr
++ = v
= cell
->v
;
61 *yptr
++ = y1
= cell
->y
[1]; *uptr
++ = u
; *vptr
++ = v
;
71 yptr
+= row_inc
; uptr
+= c_row_inc
; vptr
+= c_row_inc
;
73 *yptr
++ = y0
= cell
->y
[2]; *uptr
++ = u
; *vptr
++ = v
;
75 *yptr
++ = y1
= cell
->y
[3]; *uptr
++ = u
; *vptr
++ = v
;
86 void ff_apply_motion_4x4(RoqContext
*ri
, int x
, int y
,
87 int deltax
, int deltay
)
90 unsigned char *pa
, *pb
;
95 /* check MV against frame boundaries */
96 if ((mx
< 0) || (mx
> ri
->avctx
->width
- 4) ||
97 (my
< 0) || (my
> ri
->avctx
->height
- 4)) {
98 av_log(ri
->avctx
, AV_LOG_ERROR
, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)\n",
99 mx
, my
, ri
->avctx
->width
, ri
->avctx
->height
);
103 pa
= ri
->current_frame
->data
[0] + (y
* ri
->y_stride
) + x
;
104 pb
= ri
->last_frame
->data
[0] + (my
* ri
->y_stride
) + mx
;
105 for(i
= 0; i
< 4; i
++) {
115 pa
= ri
->current_frame
->data
[1] + (y
* ri
->y_stride
)/4 + x
/2;
116 pb
= ri
->last_frame
->data
[1] + (my
/2) * (ri
->y_stride
/2) + (mx
+ 1)/2;
118 for(i
= 0; i
< 2; i
++) {
119 switch(((my
& 0x01) << 1) | (mx
& 0x01)) {
129 pa
[0] = avg2(pb
[0], pb
[1]);
130 pa
[1] = avg2(pb
[1], pb
[2]);
131 pa
[hw
] = avg2(pb
[hw
], pb
[hw
+1]);
132 pa
[hw
+1] = avg2(pb
[hw
+1], pb
[hw
+2]);
136 pa
[0] = avg2(pb
[0], pb
[hw
]);
137 pa
[1] = avg2(pb
[1], pb
[hw
+1]);
138 pa
[hw
] = avg2(pb
[hw
], pb
[hw
*2]);
139 pa
[hw
+1] = avg2(pb
[hw
+1], pb
[(hw
*2)+1]);
143 pa
[0] = avg4(pb
[0], pb
[1], pb
[hw
], pb
[hw
+1]);
144 pa
[1] = avg4(pb
[1], pb
[2], pb
[hw
+1], pb
[hw
+2]);
145 pa
[hw
] = avg4(pb
[hw
], pb
[hw
+1], pb
[hw
*2], pb
[(hw
*2)+1]);
146 pa
[hw
+1] = avg4(pb
[hw
+1], pb
[hw
+2], pb
[(hw
*2)+1], pb
[(hw
*2)+1]);
150 pa
= ri
->current_frame
->data
[2] + (y
* ri
->y_stride
)/4 + x
/2;
151 pb
= ri
->last_frame
->data
[2] + (my
/2) * (ri
->y_stride
/2) + (mx
+ 1)/2;
155 void ff_apply_motion_8x8(RoqContext
*ri
, int x
, int y
,
156 int deltax
, int deltay
)
158 int mx
, my
, i
, j
, hw
;
159 unsigned char *pa
, *pb
;
164 /* check MV against frame boundaries */
165 if ((mx
< 0) || (mx
> ri
->avctx
->width
- 8) ||
166 (my
< 0) || (my
> ri
->avctx
->height
- 8)) {
167 av_log(ri
->avctx
, AV_LOG_ERROR
, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)\n",
168 mx
, my
, ri
->avctx
->width
, ri
->avctx
->height
);
172 pa
= ri
->current_frame
->data
[0] + (y
* ri
->y_stride
) + x
;
173 pb
= ri
->last_frame
->data
[0] + (my
* ri
->y_stride
) + mx
;
174 for(i
= 0; i
< 8; i
++) {
188 pa
= ri
->current_frame
->data
[1] + (y
* ri
->y_stride
)/4 + x
/2;
189 pb
= ri
->last_frame
->data
[1] + (my
/2) * (ri
->y_stride
/2) + (mx
+ 1)/2;
190 for(j
= 0; j
< 2; j
++) {
191 for(i
= 0; i
< 4; i
++) {
192 switch(((my
& 0x01) << 1) | (mx
& 0x01)) {
202 pa
[0] = avg2(pb
[0], pb
[1]);
203 pa
[1] = avg2(pb
[1], pb
[2]);
204 pa
[2] = avg2(pb
[2], pb
[3]);
205 pa
[3] = avg2(pb
[3], pb
[4]);
209 pa
[0] = avg2(pb
[0], pb
[hw
]);
210 pa
[1] = avg2(pb
[1], pb
[hw
+1]);
211 pa
[2] = avg2(pb
[2], pb
[hw
+2]);
212 pa
[3] = avg2(pb
[3], pb
[hw
+3]);
216 pa
[0] = avg4(pb
[0], pb
[1], pb
[hw
], pb
[hw
+1]);
217 pa
[1] = avg4(pb
[1], pb
[2], pb
[hw
+1], pb
[hw
+2]);
218 pa
[2] = avg4(pb
[2], pb
[3], pb
[hw
+2], pb
[hw
+3]);
219 pa
[3] = avg4(pb
[3], pb
[4], pb
[hw
+3], pb
[hw
+4]);
226 pa
= ri
->current_frame
->data
[2] + (y
* ri
->y_stride
)/4 + x
/2;
227 pb
= ri
->last_frame
->data
[2] + (my
/2) * (ri
->y_stride
/2) + (mx
+ 1)/2;