Commit | Line | Data |
---|---|---|
3ef8be2b MM |
1 | /* |
2 | * Copyright (C) 2003 the ffmpeg project | |
3 | * | |
b78e7197 DB |
4 | * This file is part of FFmpeg. |
5 | * | |
6 | * FFmpeg is free software; you can redistribute it and/or | |
3ef8be2b MM |
7 | * modify it under the terms of the GNU Lesser General Public |
8 | * License as published by the Free Software Foundation; either | |
b78e7197 | 9 | * version 2.1 of the License, or (at your option) any later version. |
3ef8be2b | 10 | * |
b78e7197 | 11 | * FFmpeg is distributed in the hope that it will be useful, |
3ef8be2b MM |
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. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public | |
b78e7197 | 17 | * License along with FFmpeg; if not, write to the Free Software |
5509bffa | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
3ef8be2b MM |
19 | * |
20 | */ | |
21 | ||
22 | /** | |
23 | * @file roqvideo.c | |
55c970e3 | 24 | * Id RoQ Video common functions based on work by Dr. Tim Ferguson |
3ef8be2b MM |
25 | */ |
26 | ||
3ef8be2b | 27 | #include "avcodec.h" |
55c970e3 | 28 | #include "roqvideo.h" |
3ef8be2b | 29 | |
750cbd34 VS |
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) | |
3ef8be2b | 32 | |
750cbd34 | 33 | void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell) |
3ef8be2b MM |
34 | { |
35 | unsigned char *yptr; | |
36 | ||
65a455a8 | 37 | yptr = ri->current_frame->data[0] + (y * ri->y_stride) + x; |
750cbd34 VS |
38 | *yptr++ = cell->y[0]; |
39 | *yptr++ = cell->y[1]; | |
3ef8be2b | 40 | yptr += (ri->y_stride - 2); |
750cbd34 VS |
41 | *yptr++ = cell->y[2]; |
42 | *yptr++ = cell->y[3]; | |
65a455a8 AJ |
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; | |
3ef8be2b MM |
45 | } |
46 | ||
750cbd34 | 47 | void ff_apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell) |
3ef8be2b MM |
48 | { |
49 | unsigned long row_inc, c_row_inc; | |
50 | register unsigned char y0, y1, u, v; | |
51 | unsigned char *yptr, *uptr, *vptr; | |
52 | ||
65a455a8 AJ |
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; | |
3ef8be2b MM |
56 | |
57 | row_inc = ri->y_stride - 4; | |
58 | c_row_inc = (ri->c_stride) - 2; | |
750cbd34 | 59 | *yptr++ = y0 = cell->y[0]; *uptr++ = u = cell->u; *vptr++ = v = cell->v; |
3ef8be2b | 60 | *yptr++ = y0; |
750cbd34 | 61 | *yptr++ = y1 = cell->y[1]; *uptr++ = u; *vptr++ = v; |
3ef8be2b MM |
62 | *yptr++ = y1; |
63 | ||
64 | yptr += row_inc; | |
65 | ||
66 | *yptr++ = y0; | |
67 | *yptr++ = y0; | |
68 | *yptr++ = y1; | |
69 | *yptr++ = y1; | |
70 | ||
71 | yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc; | |
72 | ||
750cbd34 | 73 | *yptr++ = y0 = cell->y[2]; *uptr++ = u; *vptr++ = v; |
3ef8be2b | 74 | *yptr++ = y0; |
750cbd34 | 75 | *yptr++ = y1 = cell->y[3]; *uptr++ = u; *vptr++ = v; |
3ef8be2b MM |
76 | *yptr++ = y1; |
77 | ||
78 | yptr += row_inc; | |
79 | ||
80 | *yptr++ = y0; | |
81 | *yptr++ = y0; | |
82 | *yptr++ = y1; | |
83 | *yptr++ = y1; | |
84 | } | |
85 | ||
750cbd34 VS |
86 | void ff_apply_motion_4x4(RoqContext *ri, int x, int y, |
87 | int deltax, int deltay) | |
3ef8be2b | 88 | { |
ec59fd53 | 89 | int i, hw, mx, my; |
3ef8be2b MM |
90 | unsigned char *pa, *pb; |
91 | ||
750cbd34 VS |
92 | mx = x + deltax; |
93 | my = y + deltay; | |
3ef8be2b | 94 | |
b9029997 MM |
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); | |
100 | return; | |
101 | } | |
102 | ||
65a455a8 AJ |
103 | pa = ri->current_frame->data[0] + (y * ri->y_stride) + x; |
104 | pb = ri->last_frame->data[0] + (my * ri->y_stride) + mx; | |
3ef8be2b MM |
105 | for(i = 0; i < 4; i++) { |
106 | pa[0] = pb[0]; | |
107 | pa[1] = pb[1]; | |
108 | pa[2] = pb[2]; | |
109 | pa[3] = pb[3]; | |
110 | pa += ri->y_stride; | |
111 | pb += ri->y_stride; | |
112 | } | |
113 | ||
ec59fd53 | 114 | hw = ri->y_stride/2; |
65a455a8 AJ |
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; | |
ec59fd53 MM |
117 | |
118 | for(i = 0; i < 2; i++) { | |
119 | switch(((my & 0x01) << 1) | (mx & 0x01)) { | |
120 | ||
121 | case 0: | |
122 | pa[0] = pb[0]; | |
123 | pa[1] = pb[1]; | |
124 | pa[hw] = pb[hw]; | |
125 | pa[hw+1] = pb[hw+1]; | |
126 | break; | |
127 | ||
128 | case 1: | |
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]); | |
133 | break; | |
134 | ||
135 | case 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]); | |
140 | break; | |
141 | ||
142 | case 3: | |
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]); | |
147 | break; | |
148 | } | |
149 | ||
65a455a8 AJ |
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; | |
ec59fd53 | 152 | } |
3ef8be2b MM |
153 | } |
154 | ||
750cbd34 VS |
155 | void ff_apply_motion_8x8(RoqContext *ri, int x, int y, |
156 | int deltax, int deltay) | |
3ef8be2b | 157 | { |
ec59fd53 | 158 | int mx, my, i, j, hw; |
3ef8be2b MM |
159 | unsigned char *pa, *pb; |
160 | ||
750cbd34 VS |
161 | mx = x + deltax; |
162 | my = y + deltay; | |
3ef8be2b | 163 | |
b9029997 MM |
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); | |
169 | return; | |
170 | } | |
171 | ||
65a455a8 AJ |
172 | pa = ri->current_frame->data[0] + (y * ri->y_stride) + x; |
173 | pb = ri->last_frame->data[0] + (my * ri->y_stride) + mx; | |
3ef8be2b MM |
174 | for(i = 0; i < 8; i++) { |
175 | pa[0] = pb[0]; | |
176 | pa[1] = pb[1]; | |
177 | pa[2] = pb[2]; | |
178 | pa[3] = pb[3]; | |
179 | pa[4] = pb[4]; | |
180 | pa[5] = pb[5]; | |
181 | pa[6] = pb[6]; | |
182 | pa[7] = pb[7]; | |
183 | pa += ri->y_stride; | |
184 | pb += ri->y_stride; | |
185 | } | |
186 | ||
ec59fd53 | 187 | hw = ri->c_stride; |
65a455a8 AJ |
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; | |
ec59fd53 MM |
190 | for(j = 0; j < 2; j++) { |
191 | for(i = 0; i < 4; i++) { | |
192 | switch(((my & 0x01) << 1) | (mx & 0x01)) { | |
193 | ||
194 | case 0: | |
195 | pa[0] = pb[0]; | |
196 | pa[1] = pb[1]; | |
197 | pa[2] = pb[2]; | |
198 | pa[3] = pb[3]; | |
199 | break; | |
200 | ||
201 | case 1: | |
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]); | |
206 | break; | |
115329f1 | 207 | |
ec59fd53 MM |
208 | case 2: |
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]); | |
213 | break; | |
214 | ||
215 | case 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]); | |
220 | break; | |
221 | } | |
222 | pa += ri->c_stride; | |
223 | pb += ri->c_stride; | |
224 | } | |
225 | ||
65a455a8 AJ |
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; | |
ec59fd53 | 228 | } |
3ef8be2b | 229 | } |