1 /* |
|
2 * Copyright (c) 2010 Ixonos Plc. |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - Initial contribution |
|
11 * |
|
12 * Contributors: |
|
13 * Ixonos Plc |
|
14 * |
|
15 * Description: |
|
16 * Motion compensation functions. |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 #include "h263dConfig.h" |
|
22 |
|
23 #include "block.h" |
|
24 |
|
25 #include "errcodes.h" |
|
26 #include "vdcmvc.h" |
|
27 #include "debug.h" |
|
28 |
|
29 #ifndef blcAssert |
|
30 #define blcAssert assert |
|
31 #endif |
|
32 #include "blcllcpy.cpp" |
|
33 |
|
34 /* See the description above. */ |
|
35 typedef void (* blcCopyBlock_t) (u_char *, u_char *, |
|
36 int, int, int, int, int, int, int, int, int, int, int, int, int); |
|
37 |
|
38 /* This structure is used to pass a pointer either to blcUVCountRefXY1MV or |
|
39 blcUVCountRefXY4MVs. */ |
|
40 typedef void (* blcUVCountRefXY_t) |
|
41 (int, int, int *, int *, int *, int *, int *, int *); |
|
42 |
|
43 |
|
44 /* |
|
45 * Local function prototypes |
|
46 */ |
|
47 |
|
48 static int blcCopyNormalYPredictionMBWith1MV( |
|
49 blcCopyBlock_t copyBlock, |
|
50 int *mvxArray, int *mvyArray, |
|
51 u_char *dstYBlk, |
|
52 u_char *srcYFrame, |
|
53 int dstYXPos, int dstYYPos, |
|
54 int dstYXSize, |
|
55 int srcYXSize, int srcYYSize, |
|
56 int fMVsOverPictureBoundaries, |
|
57 int rcontrol); |
|
58 |
|
59 static int blcCopyNormalYPredictionMBWith4MVs( |
|
60 blcCopyBlock_t copyBlock, |
|
61 int *mvxArray, int *mvyArray, |
|
62 u_char *dstYBlk, |
|
63 u_char *srcYFrame, |
|
64 int dstYXPos, int dstYYPos, |
|
65 int dstYXSize, |
|
66 int srcYXSize, int srcYYSize, |
|
67 int fMVsOverPictureBoundaries, |
|
68 int rcontrol); |
|
69 |
|
70 static int blcCopyUVPredictionBlocks( |
|
71 blcUVCountRefXY_t uvCountSourceXY, |
|
72 blcCopyBlock_t copyBlock, |
|
73 int *mvxArray, int *mvyArray, |
|
74 u_char *dstUBlk, u_char *dstVBlk, |
|
75 u_char *srcUFrame, u_char *srcVFrame, |
|
76 int dstUVXPos, int dstUVYPos, |
|
77 int dstUVXSize, |
|
78 int srcUVXSize, int srcUVYSize, |
|
79 int fMVsOverPictureBoundaries, |
|
80 int rcontrol); |
|
81 |
|
82 static void blcHandleRefOverPictBoundariesBC( |
|
83 int xBlkSize, int yBlkSize, |
|
84 int xSize, int ySize, |
|
85 int subpixelX, int subpixelY, |
|
86 int *sourceX, int *sourceY, |
|
87 int *xlt0, int *xNormal, int *xgtmax, |
|
88 int *ylt0, int *yNormal, int *ygtmax); |
|
89 |
|
90 static int blcIsRefOverPictBoundaries( |
|
91 int xBlkSize, int yBlkSize, |
|
92 int xSize, int ySize, |
|
93 int subpixelX, int subpixelY, |
|
94 int sourceX, int sourceY); |
|
95 |
|
96 static void blcUVCountMVOffset4MVs( |
|
97 int *mvxArray, int *mvyArray, |
|
98 int *offsetX, int *offsetY, |
|
99 int *subpixelX, int *subpixelY); |
|
100 |
|
101 static void blcUVCountRefXY1MV( |
|
102 int origoX, int origoY, |
|
103 int *mvxArray, int *mvyArray, |
|
104 int *sourceX, int *sourceY, |
|
105 int *subpixelX, int *subpixelY); |
|
106 |
|
107 static void blcUVCountRefXY4MVs( |
|
108 int origoX, int origoY, |
|
109 int *mvxArray, int *mvyArray, |
|
110 int *sourceX, int *sourceY, |
|
111 int *subpixelX, int *subpixelY); |
|
112 |
|
113 static void blcYCountRefXY( |
|
114 int mvxVal, int mvyVal, |
|
115 int destX, int destY, |
|
116 int *sourceX, int *sourceY, |
|
117 int *subpixelX, int *subpixelY); |
|
118 |
|
119 |
|
120 /* |
|
121 * Module-scope constants |
|
122 */ |
|
123 |
|
124 /* Clipping table to sature values to range 0..255 */ |
|
125 static const u_char wholeClippingTable[4*256] = { |
|
126 0, 0, 0, 0, 0, 0, 0, |
|
127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
137 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
141 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
142 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
147 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
148 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
151 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
158 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
160 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
161 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
162 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
163 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
164 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
165 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
166 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
173 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
175 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
177 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, |
|
178 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
|
179 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, |
|
180 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, |
|
181 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, |
|
182 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, |
|
183 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, |
|
184 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, |
|
185 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, |
|
186 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, |
|
187 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, |
|
188 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, |
|
189 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, |
|
190 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, |
|
191 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, |
|
192 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, |
|
193 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, |
|
194 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, |
|
195 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, |
|
196 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, |
|
197 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, |
|
198 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, |
|
199 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, |
|
200 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, |
|
201 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, |
|
202 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, |
|
203 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
204 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
205 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
206 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
207 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
208 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
209 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
210 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
211 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
212 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
213 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
214 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
215 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
216 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
217 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
218 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
219 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
220 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
221 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
222 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
223 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
224 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
225 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
226 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
227 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
|
228 255, 255, 255, 255, 255, 255, 255}; |
|
229 |
|
230 static const u_char * const clippingTable = &wholeClippingTable[512]; |
|
231 |
|
232 |
|
233 /* |
|
234 * Global functions |
|
235 */ |
|
236 |
|
237 /* {{-output"blcAddBlock.txt"}} */ |
|
238 /* |
|
239 * blcAddBlock |
|
240 * |
|
241 * |
|
242 * Parameters: |
|
243 * block block array (of 64 pixels) |
|
244 * dstBlk pointer to present frame in the place, |
|
245 * where the block is added |
|
246 * xSize X size of the frame. |
|
247 * mbPlace flag that indicates the place for the current |
|
248 * macroblock inside the macroblock row: |
|
249 * -1 beginning of row |
|
250 * 0 middle of row |
|
251 * 1 end of row |
|
252 * fourMVs 1 if Advanced Prediction Mode is used, otherwise 0 |
|
253 * prevDiffBlock if fourMVs == 1 and mbPlace <= 0 the difference |
|
254 * block is stored to prevDiffBlock for later use |
|
255 * |
|
256 * Function: |
|
257 * This function sums the given block into block being currently decoded in |
|
258 * present frame. Parameters are the table consisting a block, a pointer to |
|
259 * the frame at the correct place and the width of the frame. |
|
260 * |
|
261 * Returns: |
|
262 * Nothing. |
|
263 * |
|
264 */ |
|
265 |
|
266 void blcAddBlock(int *block, u_char *dstBlk, int xSize, |
|
267 int mbPlace, u_char fourMVs, int *prevDiffBlock) |
|
268 /* {{-output"blcAddBlock.txt"}} */ |
|
269 { |
|
270 int i; |
|
271 |
|
272 if (fourMVs && mbPlace <= 0) { |
|
273 MEMCPY(prevDiffBlock, block, 64 * sizeof(int)); |
|
274 } |
|
275 else { |
|
276 for(i = 8; i; i--) { |
|
277 *dstBlk++ = clippingTable[*dstBlk + *block++]; |
|
278 *dstBlk++ = clippingTable[*dstBlk + *block++]; |
|
279 *dstBlk++ = clippingTable[*dstBlk + *block++]; |
|
280 *dstBlk++ = clippingTable[*dstBlk + *block++]; |
|
281 *dstBlk++ = clippingTable[*dstBlk + *block++]; |
|
282 *dstBlk++ = clippingTable[*dstBlk + *block++]; |
|
283 *dstBlk++ = clippingTable[*dstBlk + *block++]; |
|
284 *dstBlk++ = clippingTable[*dstBlk + *block++]; |
|
285 dstBlk += xSize - 8; |
|
286 } |
|
287 } |
|
288 } |
|
289 |
|
290 |
|
291 /* {{-output"blcBlockToFrame.txt"}} */ |
|
292 /* |
|
293 * blcBlockToFrame |
|
294 * |
|
295 * |
|
296 * Parameters: |
|
297 * block block array (of 64 pixels) |
|
298 * dstBlk pointer to present frame in the place, where the block is |
|
299 * written |
|
300 * xSize X size of the frame. |
|
301 * |
|
302 * Function: |
|
303 * This function writes the given block into block being currently decoded |
|
304 * in present frame. Parameters are the table consisting a block, a pointer |
|
305 * to the frame at the correct place and the width of the frame. |
|
306 * |
|
307 * Returns: |
|
308 * Nothing. |
|
309 * |
|
310 */ |
|
311 |
|
312 void blcBlockToFrame(int *block, u_char *dstBlk, int xSize) |
|
313 /* {{-output"blcBlockToFrame.txt"}} */ |
|
314 { |
|
315 int i; |
|
316 |
|
317 for( i = 0; i < 8; i++ ) |
|
318 { |
|
319 *dstBlk = clippingTable[ *block ]; |
|
320 *(dstBlk+1) = clippingTable[ *(block+1) ]; |
|
321 *(dstBlk+2) = clippingTable[ *(block+2) ]; |
|
322 *(dstBlk+3) = clippingTable[ *(block+3) ]; |
|
323 *(dstBlk+4) = clippingTable[ *(block+4) ]; |
|
324 *(dstBlk+5) = clippingTable[ *(block+5) ]; |
|
325 *(dstBlk+6) = clippingTable[ *(block+6) ]; |
|
326 *(dstBlk+7) = clippingTable[ *(block+7) ]; |
|
327 dstBlk += xSize; |
|
328 block += 8; |
|
329 } |
|
330 } |
|
331 |
|
332 |
|
333 /* {{-output"blcCopyPredictionMB.txt"}} */ |
|
334 /* |
|
335 * blcCopyPredictionMB |
|
336 * |
|
337 * |
|
338 * Parameters: |
|
339 * param input and output parameters |
|
340 * |
|
341 * Function: |
|
342 * This function copies one macroblock from previous frame into present |
|
343 * frame at the location of macroblock being currently decoded. |
|
344 * The location where the macroblock is read is the location of |
|
345 * the current block changed with motion vectors. |
|
346 * |
|
347 * Returns: |
|
348 * >= 0 the function was successful |
|
349 * < 0 an error occured |
|
350 * |
|
351 */ |
|
352 |
|
353 int blcCopyPredictionMB(blcCopyPredictionMBParam_t *param) |
|
354 /* {{-output"blcCopyPredictionMB.txt"}} */ |
|
355 { |
|
356 int |
|
357 uvWidth = param->uvWidth, |
|
358 uvHeight = param->uvHeight, |
|
359 yWidth = uvWidth * 2, |
|
360 yHeight = uvHeight * 2, |
|
361 uvDstX = param->uvBlkXCoord, |
|
362 uvDstY = param->uvBlkYCoord, |
|
363 yDstX = uvDstX * 2, |
|
364 yDstY = uvDstY * 2, |
|
365 *mvx = param->mvx, |
|
366 *mvy = param->mvy, |
|
367 status; |
|
368 |
|
369 u_char |
|
370 *dstYBlk = param->currYMBInFrame, |
|
371 *dstUBlk = param->currUBlkInFrame, |
|
372 *dstVBlk = param->currVBlkInFrame, |
|
373 *srcYFrame = param->refY, |
|
374 *srcUFrame = param->refU, |
|
375 *srcVFrame = param->refV; |
|
376 |
|
377 blcCopyBlock_t copyBlock = (param->fMVsOverPictureBoundaries) ? |
|
378 blcCopyBlockBC : blcCopyBlockNBC; |
|
379 |
|
380 blcAssert(param != NULL); |
|
381 blcAssert(param->rcontrol == 0 || param->rcontrol == 1); |
|
382 |
|
383 /* Copy UV prediction blocks */ |
|
384 status = blcCopyUVPredictionBlocks( |
|
385 (param->fourMVs) ? |
|
386 blcUVCountRefXY4MVs : blcUVCountRefXY1MV, |
|
387 copyBlock, |
|
388 mvx, mvy, |
|
389 dstUBlk, dstVBlk, |
|
390 srcUFrame, srcVFrame, |
|
391 uvDstX, uvDstY, |
|
392 uvWidth, |
|
393 uvWidth, uvHeight, |
|
394 param->fMVsOverPictureBoundaries, |
|
395 param->rcontrol); |
|
396 |
|
397 if (status < 0) |
|
398 return status; |
|
399 |
|
400 /* If Advanced Prediction is in use */ |
|
401 if (param->fAdvancedPrediction) { |
|
402 |
|
403 // not supported |
|
404 |
|
405 } |
|
406 |
|
407 /* Else normal prediction mode is in use */ |
|
408 else { |
|
409 |
|
410 /* Copy Y prediction MB */ |
|
411 if(param->fourMVs) |
|
412 status = blcCopyNormalYPredictionMBWith4MVs( |
|
413 copyBlock, |
|
414 mvx, mvy, |
|
415 dstYBlk, |
|
416 srcYFrame, |
|
417 yDstX, yDstY, |
|
418 yWidth, |
|
419 yWidth, yHeight, |
|
420 param->fMVsOverPictureBoundaries, |
|
421 param->rcontrol); |
|
422 else |
|
423 status = blcCopyNormalYPredictionMBWith1MV( |
|
424 copyBlock, |
|
425 mvx, mvy, |
|
426 dstYBlk, |
|
427 srcYFrame, |
|
428 yDstX, yDstY, |
|
429 yWidth, |
|
430 yWidth, yHeight, |
|
431 param->fMVsOverPictureBoundaries, |
|
432 param->rcontrol); |
|
433 if (status < 0) |
|
434 return status; |
|
435 } |
|
436 |
|
437 return 0; |
|
438 } |
|
439 |
|
440 |
|
441 |
|
442 |
|
443 |
|
444 /* |
|
445 * Local functions |
|
446 */ |
|
447 |
|
448 |
|
449 |
|
450 |
|
451 |
|
452 /* |
|
453 * blcCopyNormalYPredictionMBWith1MV |
|
454 * |
|
455 * |
|
456 * Parameters: |
|
457 * copyBlock a pointer to either blcCopyBlockBC or |
|
458 * blcCopyBlockNBC (or their Assembler versions) |
|
459 * |
|
460 * mvxArray an array of four for x component of MVs |
|
461 * mvyArray an array of four for y component of MVs |
|
462 * (Only the first entry of the array is used.) |
|
463 * |
|
464 * dstYBlk a pointer to the current Y macroblock |
|
465 * in the destination Y frame |
|
466 * |
|
467 * srcYFrame the top-left corner of the source Y frame |
|
468 * |
|
469 * dstYXPos the x coordinate of dstYBlk (in pixels) |
|
470 * dstYYPos the y coordinate of dstYBlk (in pixels) |
|
471 * |
|
472 * dstYXSize the width of the Y destination frame |
|
473 * srcYXSize the width of the Y source frame |
|
474 * srcYYSize the height of the Y source frame |
|
475 * |
|
476 * fMVsOverPictureBoundaries non-zero if motion vectors may point outside |
|
477 * picture boundaries, zero otherwise |
|
478 * |
|
479 * rcontrol RCONTROL (section 6.1.2 of the H.263 standard) |
|
480 * |
|
481 * Function: |
|
482 * This function copies a luminance prediction macroblock from the given |
|
483 * source frame to the given position of the destination frame. |
|
484 * The prediction macroblock is associated with one motion vector. |
|
485 * |
|
486 * Returns: |
|
487 * >= 0 if everything is ok |
|
488 * < 0 if an error occured |
|
489 * |
|
490 */ |
|
491 |
|
492 static int blcCopyNormalYPredictionMBWith1MV( |
|
493 blcCopyBlock_t copyBlock, |
|
494 int *mvxArray, int *mvyArray, |
|
495 u_char *dstYBlk, |
|
496 u_char *srcYFrame, |
|
497 int dstYXPos, int dstYYPos, |
|
498 int dstYXSize, |
|
499 int srcYXSize, int srcYYSize, |
|
500 int fMVsOverPictureBoundaries, |
|
501 int rcontrol) |
|
502 { |
|
503 int |
|
504 mvxVal = *mvxArray, mvyVal = *mvyArray, |
|
505 subpixelX, subpixelY, |
|
506 xlt0, xNormal, xgtmax, |
|
507 ylt0, yNormal, ygtmax, |
|
508 srcXPos, srcYPos; |
|
509 u_char *srcBlk; |
|
510 |
|
511 blcYCountRefXY(mvxVal, mvyVal, dstYXPos, dstYYPos, &srcXPos, &srcYPos, |
|
512 &subpixelX, &subpixelY); |
|
513 |
|
514 if (fMVsOverPictureBoundaries) |
|
515 blcHandleRefOverPictBoundariesBC( |
|
516 16, 16, |
|
517 srcYXSize, srcYYSize, |
|
518 subpixelX, subpixelY, |
|
519 &srcXPos, &srcYPos, |
|
520 &xlt0, &xNormal, &xgtmax, |
|
521 &ylt0, &yNormal, &ygtmax); |
|
522 |
|
523 else { |
|
524 if (blcIsRefOverPictBoundaries( |
|
525 16, 16, |
|
526 srcYXSize, srcYYSize, |
|
527 subpixelX, subpixelY, |
|
528 srcXPos, srcYPos)) |
|
529 return -1; |
|
530 xlt0 = xgtmax = ylt0 = ygtmax = 0; |
|
531 xNormal = yNormal = 16; |
|
532 } |
|
533 |
|
534 srcBlk = srcYFrame + srcYPos * srcYXSize + srcXPos; |
|
535 |
|
536 copyBlock(srcBlk, dstYBlk, xlt0, xNormal, xgtmax, |
|
537 ylt0, yNormal, ygtmax, subpixelX, subpixelY, |
|
538 srcYXSize, dstYXSize, 16, 16, rcontrol); |
|
539 |
|
540 return 0; |
|
541 } |
|
542 |
|
543 |
|
544 /* |
|
545 * blcCopyNormalYPredictionMBWith4MVs |
|
546 * |
|
547 * |
|
548 * Parameters: |
|
549 * See blcCopyNormalYPredictionMBWith1MV. |
|
550 * All 4 entries of mvxArray and mvyArray are used. |
|
551 * |
|
552 * Function: |
|
553 * This function copies a luminance prediction macroblock from the given |
|
554 * source frame to the given position of the destination frame. |
|
555 * The prediction macroblock is associated with four motion vectors. |
|
556 * |
|
557 * Returns: |
|
558 * >= 0 if everything is ok |
|
559 * < 0 if an error occured |
|
560 * |
|
561 */ |
|
562 |
|
563 static int blcCopyNormalYPredictionMBWith4MVs( |
|
564 blcCopyBlock_t copyBlock, |
|
565 int *mvxArray, int *mvyArray, |
|
566 u_char *dstYBlk, |
|
567 u_char *srcYFrame, |
|
568 int dstYXPos, int dstYYPos, |
|
569 int dstYXSize, |
|
570 int srcYXSize, int srcYYSize, |
|
571 int fMVsOverPictureBoundaries, |
|
572 int rcontrol) |
|
573 { |
|
574 int |
|
575 nh, nv, |
|
576 mvi = 0, |
|
577 mvxVal, mvyVal, |
|
578 subpixelX, subpixelY, |
|
579 xlt0, xNormal, xgtmax, |
|
580 ylt0, yNormal, ygtmax, |
|
581 srcXPos, srcYPos; |
|
582 |
|
583 u_char |
|
584 *srcBlk, |
|
585 *origDest; |
|
586 |
|
587 origDest = dstYBlk; |
|
588 for (nv = 0; nv <= 1; nv++, dstYYPos += 8, |
|
589 origDest += (dstYXSize << 3) - 16, dstYXPos -= 16) { |
|
590 for (nh = 0; nh <= 1; nh++, dstYXPos += 8, origDest += 8, mvi++) { |
|
591 dstYBlk = origDest; |
|
592 mvxVal = mvxArray[mvi]; |
|
593 mvyVal = mvyArray[mvi]; |
|
594 |
|
595 blcYCountRefXY(mvxVal, mvyVal, dstYXPos, dstYYPos, &srcXPos, &srcYPos, |
|
596 &subpixelX, &subpixelY); |
|
597 |
|
598 if (fMVsOverPictureBoundaries) |
|
599 blcHandleRefOverPictBoundariesBC( |
|
600 8, 8, |
|
601 srcYXSize, srcYYSize, |
|
602 subpixelX, subpixelY, |
|
603 &srcXPos, &srcYPos, |
|
604 &xlt0, &xNormal, &xgtmax, |
|
605 &ylt0, &yNormal, &ygtmax); |
|
606 |
|
607 else { |
|
608 if (blcIsRefOverPictBoundaries( |
|
609 8, 8, |
|
610 srcYXSize, srcYYSize, |
|
611 subpixelX, subpixelY, |
|
612 srcXPos, srcYPos)) |
|
613 return -1; |
|
614 xlt0 = xgtmax = ylt0 = ygtmax = 0; |
|
615 xNormal = yNormal = 8; |
|
616 } |
|
617 |
|
618 srcBlk = srcYFrame + srcYPos * srcYXSize + srcXPos; |
|
619 |
|
620 copyBlock(srcBlk, dstYBlk, xlt0, xNormal, xgtmax, |
|
621 ylt0, yNormal, ygtmax, subpixelX, subpixelY, srcYXSize, |
|
622 dstYXSize, 8, 8, rcontrol); |
|
623 } |
|
624 } |
|
625 |
|
626 return 0; |
|
627 } |
|
628 |
|
629 |
|
630 |
|
631 /* |
|
632 * blcCopyUVPredictionBlocks |
|
633 * |
|
634 * |
|
635 * Parameters: |
|
636 * uvCountSourceXY a pointer to either blcUVCountRefXY1MV or |
|
637 * blcUVCountRefXY4MVs |
|
638 * |
|
639 * copyBlock a pointer to either blcCopyBlockBC or |
|
640 * blcCopyBlockNBC (or their Assembler versions) |
|
641 * |
|
642 * mvxArray an array of four for x component of MVs |
|
643 * mvyArray an array of four for y component of MVs |
|
644 * |
|
645 * dstUBlk a pointer to the current U block |
|
646 * in the destination U frame |
|
647 * dstVBlk a pointer to the current V block |
|
648 * in the destination V frame |
|
649 * |
|
650 * srcUFrame the top-left corner of the source U frame |
|
651 * srcVFrame the top-left corner of the source V frame |
|
652 * |
|
653 * dstUVXPos the x coordinate of dstUBlk |
|
654 * dstUVYPos the y coordinate of dstUBlk |
|
655 * |
|
656 * dstUVXSize the width of the U and V destination frame |
|
657 * srcUVXSize the width of the U and V source frame |
|
658 * srcUVYSize the height of the U and V source frame |
|
659 * |
|
660 * fMVsOverPictureBoundaries non-zero if motion vectors may point outside |
|
661 * picture boundaries, zero otherwise |
|
662 * |
|
663 * rcontrol RCONTROL (section 6.1.2 of the H.263 standard) |
|
664 * |
|
665 * Function: |
|
666 * This function copies chrominance prediction blocks from the given |
|
667 * source frames to the given positions of the destination frames. |
|
668 * |
|
669 * Returns: |
|
670 * >= 0 if everything is ok |
|
671 * < 0 if an error occured |
|
672 * |
|
673 */ |
|
674 |
|
675 static int blcCopyUVPredictionBlocks( |
|
676 blcUVCountRefXY_t uvCountSourceXY, |
|
677 blcCopyBlock_t copyBlock, |
|
678 int *mvxArray, int *mvyArray, |
|
679 u_char *dstUBlk, u_char *dstVBlk, |
|
680 u_char *srcUFrame, u_char *srcVFrame, |
|
681 int dstUVXPos, int dstUVYPos, |
|
682 int dstUVXSize, |
|
683 int srcUVXSize, int srcUVYSize, |
|
684 int fMVsOverPictureBoundaries, |
|
685 int rcontrol) |
|
686 { |
|
687 int |
|
688 srcXPos, |
|
689 srcYPos, |
|
690 subpixelX, |
|
691 subpixelY, |
|
692 xlt0, |
|
693 xNormal, |
|
694 xgtmax, |
|
695 ylt0, |
|
696 yNormal, |
|
697 ygtmax; |
|
698 |
|
699 u_char *srcBlk; |
|
700 |
|
701 uvCountSourceXY(dstUVXPos, dstUVYPos, mvxArray, mvyArray, |
|
702 &srcXPos, &srcYPos, &subpixelX, &subpixelY); |
|
703 |
|
704 if (fMVsOverPictureBoundaries) |
|
705 blcHandleRefOverPictBoundariesBC( |
|
706 8, 8, |
|
707 srcUVXSize, srcUVYSize, |
|
708 subpixelX, subpixelY, |
|
709 &srcXPos, &srcYPos, |
|
710 &xlt0, &xNormal, &xgtmax, |
|
711 &ylt0, &yNormal, &ygtmax); |
|
712 |
|
713 else { |
|
714 if (blcIsRefOverPictBoundaries( |
|
715 8, 8, |
|
716 srcUVXSize, srcUVYSize, |
|
717 subpixelX, subpixelY, |
|
718 srcXPos, srcYPos)) |
|
719 return -1; |
|
720 xlt0 = xgtmax = ylt0 = ygtmax = 0; |
|
721 xNormal = yNormal = 8; |
|
722 } |
|
723 |
|
724 /* U block */ \ |
|
725 srcBlk = srcUFrame + srcYPos * srcUVXSize + srcXPos; |
|
726 |
|
727 /*deb0p("Copy U block\n"); |
|
728 deb1p("srcBlk %x\n", srcBlk); |
|
729 deb1p("dstUBlk %x\n", dstUBlk); |
|
730 deb1p("xlt0 %d\n", xlt0); |
|
731 deb1p("xNormal %d\n", xNormal); |
|
732 deb1p("xgtmax %d\n", xgtmax); |
|
733 deb1p("ylt0 %d\n", ylt0); |
|
734 deb1p("yNormal %d\n", yNormal); |
|
735 deb1p("ygtmax %d\n", ygtmax); |
|
736 deb1p("subpixelX %d\n", subpixelX); |
|
737 deb1p("subpixelY %d\n", subpixelY); |
|
738 deb1p("srcUVXSize %d\n", srcUVXSize); |
|
739 deb1p("dstUVXSize %d\n", dstUVXSize); |
|
740 deb1p("rcontrol %d\n", rcontrol);*/ |
|
741 |
|
742 copyBlock(srcBlk, dstUBlk, xlt0, xNormal, xgtmax, |
|
743 ylt0, yNormal, ygtmax, subpixelX, subpixelY, |
|
744 srcUVXSize, dstUVXSize, 8, 8, rcontrol); |
|
745 |
|
746 /* V block */ \ |
|
747 srcBlk = srcVFrame + srcYPos * srcUVXSize + srcXPos; |
|
748 |
|
749 copyBlock(srcBlk, dstVBlk, xlt0, xNormal, xgtmax, |
|
750 ylt0, yNormal, ygtmax, subpixelX, subpixelY, |
|
751 srcUVXSize, dstUVXSize, 8, 8, rcontrol); |
|
752 |
|
753 return 0; |
|
754 } |
|
755 |
|
756 |
|
757 /* |
|
758 * blcHandleRefOverPictBoundariesBC |
|
759 * |
|
760 * |
|
761 * Input parameters: |
|
762 * xBlkSize the width of the block to copy |
|
763 * yBlkSize the height of the block to copy |
|
764 * xSize the width of the frame |
|
765 * ySize the height of the frame |
|
766 * |
|
767 * subpixelX 1 if half pixel position is used in X direction |
|
768 * subpixelY 1 if half pixel position is used in Y direction |
|
769 * |
|
770 * Input/output parameters: |
|
771 * sourceX input: the absolute position of the source |
|
772 * sourceY block (may be negative, half-pixel values are |
|
773 * truncated to the next smaller integer) |
|
774 * output: the coordinates of the first valid |
|
775 * pixel in the source block |
|
776 * |
|
777 * Output parameters: |
|
778 * The next parameters describe a row of source pixels. |
|
779 * xlt0 the number of the source pixels in the left of |
|
780 * the image area |
|
781 * xNormal the number of the source pixels within |
|
782 * the image area |
|
783 * xgtmax the number of the source pixels in the right of |
|
784 * the image area |
|
785 * |
|
786 * The next parameters describe a column of source pixels. |
|
787 * ylt0 the number of the source pixels above |
|
788 * the image area |
|
789 * yNormal the number of the source pixels withing |
|
790 * the image area |
|
791 * ygtmax the number of the source pixels below |
|
792 * the image area |
|
793 * |
|
794 * Function: |
|
795 * This function counts how many pixels are outside the picture area |
|
796 * and the coordinates of the first valid pixel in the source block. |
|
797 * |
|
798 * Returns: |
|
799 * See output parameters. |
|
800 * |
|
801 */ |
|
802 |
|
803 static void blcHandleRefOverPictBoundariesBC( |
|
804 int xBlkSize, int yBlkSize, |
|
805 int xSize, int ySize, |
|
806 int subpixelX, int subpixelY, |
|
807 int *sourceX, int *sourceY, |
|
808 int *xlt0, int *xNormal, int *xgtmax, |
|
809 int *ylt0, int *yNormal, int *ygtmax) |
|
810 { |
|
811 int |
|
812 xSizeMinus = xSize - xBlkSize, |
|
813 ySizeMinus = ySize - yBlkSize; |
|
814 |
|
815 if (*sourceX < 0) { |
|
816 *xlt0 = (-(*sourceX) < xBlkSize) ? -(*sourceX) : xBlkSize; |
|
817 *sourceX = 0; |
|
818 } |
|
819 else *xlt0 = 0; |
|
820 |
|
821 if (*sourceY < 0) { |
|
822 *ylt0 = (-(*sourceY) < yBlkSize) ? -(*sourceY) : yBlkSize; |
|
823 *sourceY = 0; |
|
824 } |
|
825 else *ylt0 = 0; |
|
826 |
|
827 if (*sourceX + subpixelX > xSizeMinus) { |
|
828 if (*sourceX + subpixelX < xSize) |
|
829 *xgtmax = *sourceX + subpixelX - xSizeMinus; |
|
830 else { |
|
831 *xgtmax = xBlkSize; |
|
832 *sourceX = xSize - 1; |
|
833 } |
|
834 } |
|
835 else *xgtmax = 0; |
|
836 |
|
837 if (*sourceY + subpixelY > ySizeMinus) { |
|
838 if (*sourceY + subpixelY < ySize) |
|
839 *ygtmax = *sourceY + subpixelY - ySizeMinus; |
|
840 else { |
|
841 *ygtmax = yBlkSize; |
|
842 *sourceY = ySize - 1; |
|
843 } |
|
844 } |
|
845 else *ygtmax = 0; |
|
846 |
|
847 *xNormal = xBlkSize - *xgtmax - *xlt0; |
|
848 *yNormal = yBlkSize - *ygtmax - *ylt0; |
|
849 } |
|
850 |
|
851 |
|
852 /* |
|
853 * blcIsRefOverPictBoundaries |
|
854 * |
|
855 * |
|
856 * Input parameters: |
|
857 * xBlkSize the width of the block to copy |
|
858 * yBlkSize the height of the block to copy |
|
859 * xSize the width of the frame |
|
860 * ySize the height of the frame |
|
861 * |
|
862 * subpixelX 1 if half pixel position is used in X direction |
|
863 * subpixelY 1 if half pixel position is used in Y direction |
|
864 * |
|
865 * sourceX the absolute position of the source |
|
866 * sourceY block (may be negative, half-pixel values are |
|
867 * truncated to the next smaller integer) |
|
868 * |
|
869 * Function: |
|
870 * This function checks if the reference (source, prediction) block |
|
871 * is (partly) outside the picture area. |
|
872 * |
|
873 * Returns: |
|
874 * 1 if the reference block is (partly) outside the picture area |
|
875 * 0 if the whole reference block is inside the picture area |
|
876 * |
|
877 */ |
|
878 |
|
879 static int blcIsRefOverPictBoundaries( |
|
880 int xBlkSize, int yBlkSize, |
|
881 int xSize, int ySize, |
|
882 int subpixelX, int subpixelY, |
|
883 int sourceX, int sourceY) |
|
884 { |
|
885 if (sourceX < 0) |
|
886 return 1; |
|
887 |
|
888 if (sourceY < 0) |
|
889 return 1; |
|
890 |
|
891 if (sourceX + subpixelX > xSize - xBlkSize) |
|
892 return 1; |
|
893 |
|
894 if (sourceY + subpixelY > ySize - yBlkSize) |
|
895 return 1; |
|
896 |
|
897 return 0; |
|
898 } |
|
899 |
|
900 |
|
901 |
|
902 /* |
|
903 * blcUVCountMVOffset4MVs |
|
904 * |
|
905 * |
|
906 * Input parameters: |
|
907 * mvxArray an array of the four horizontal components of |
|
908 * the motion vectors for a particular macroblock |
|
909 * mvyArray an array of the four vertical components of |
|
910 * the motion vectors for a particular macroblock |
|
911 * |
|
912 * Output parameters: |
|
913 * offsetX the relative position of the source |
|
914 * offsetY block (the origo is the destination block, |
|
915 * half-pixel values are truncated to the next |
|
916 * smaller integer) |
|
917 * |
|
918 * subpixelX 1 if half pixel position is used in X direction |
|
919 * subpixelY 1 if half pixel position is used in Y direction |
|
920 * |
|
921 * Function: |
|
922 * This function counts the relative position of the chrominance source block |
|
923 * when it is given the motion vectors for the destination block. The macro |
|
924 * uses interpolation of four motion vectors described in Annex F of H.263 |
|
925 * Recommendation. |
|
926 * |
|
927 * Returns: |
|
928 * See output parameters. |
|
929 * |
|
930 * |
|
931 * |
|
932 */ |
|
933 |
|
934 static void blcUVCountMVOffset4MVs( |
|
935 int *mvxArray, int *mvyArray, |
|
936 int *offsetX, int *offsetY, |
|
937 int *subpixelX, int *subpixelY) |
|
938 { |
|
939 /* These arrays define the table 16 in H.263 recommendation which is used |
|
940 for interpolating chrominance motion vectors when four motion vectors |
|
941 per macroblock is used. */ |
|
942 static const int |
|
943 halfPixelOrig16[31] = |
|
944 {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, |
|
945 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, |
|
946 * const halfPixel16 = &halfPixelOrig16[15], |
|
947 fullPixelOrig16[31] = |
|
948 {-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
949 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, |
|
950 * const fullPixel16 = &fullPixelOrig16[15]; |
|
951 |
|
952 int mvSum, pixelPos; |
|
953 |
|
954 mvSum = mvxArray[0] + mvxArray[1] + mvxArray[2] + mvxArray[3]; |
|
955 pixelPos = (mvSum % 80) / 5; |
|
956 *subpixelX = halfPixel16[pixelPos]; |
|
957 *offsetX = (mvSum / 80) + fullPixel16[pixelPos]; |
|
958 if (mvSum < 0 && *subpixelX) |
|
959 (*offsetX)--; |
|
960 |
|
961 mvSum = mvyArray[0] + mvyArray[1] + mvyArray[2] + mvyArray[3]; |
|
962 pixelPos = (mvSum % 80) / 5; |
|
963 *subpixelY = halfPixel16[pixelPos]; |
|
964 *offsetY = (mvSum / 80) + fullPixel16[pixelPos]; |
|
965 if (mvSum < 0 && *subpixelY) |
|
966 (*offsetY)--; |
|
967 } |
|
968 |
|
969 |
|
970 /* |
|
971 * blcUVCountRefXY1MV |
|
972 * blcUVCountRefXY4MVs |
|
973 * |
|
974 * |
|
975 * Input parameters: |
|
976 * origoX the coordinates of the destination block |
|
977 * origoY |
|
978 * |
|
979 * mvxArray an array of the four horizontal components of |
|
980 * the motion vectors for a particular macroblock |
|
981 * mvyArray an array of the four vertical components of |
|
982 * the motion vectors for a particular macroblock |
|
983 * In blcUVCountRefXY1MV, only the first entry of |
|
984 * the array is used. |
|
985 * |
|
986 * Output parameters: |
|
987 * sourceX the absolute position of the source |
|
988 * sourceY block (may be negative, half-pixel values are |
|
989 * truncated to the next smaller integer) |
|
990 * |
|
991 * subpixelX 1 if half pixel position is used in X direction |
|
992 * subpixelY 1 if half pixel position is used in Y direction |
|
993 * |
|
994 * Function: |
|
995 * These macros count the absolute position of the chrominance source block |
|
996 * (and sets sourceX, sourceY, subpixelX and subpixelY according to it) |
|
997 * when it is given the position of the destination block and |
|
998 * the motion vectors for the destination block. blcUVCountRefXY4MVs |
|
999 * uses interpolation of four motion vectors described in Annex F of H.263 |
|
1000 * Recommendation. blcUVCountRefXY1MV uses only the first motion vector |
|
1001 * of the array as described in chapter 6.1.1 of H.263 Recommendation. |
|
1002 * |
|
1003 * Returns: |
|
1004 * See output parameters. |
|
1005 * |
|
1006 * |
|
1007 * |
|
1008 */ |
|
1009 |
|
1010 static void blcUVCountRefXY1MV( |
|
1011 int origoX, int origoY, |
|
1012 int *mvxArray, int *mvyArray, |
|
1013 int *sourceX, int *sourceY, |
|
1014 int *subpixelX, int *subpixelY) |
|
1015 { |
|
1016 int mvxVal = *mvxArray, mvyVal = *mvyArray; |
|
1017 |
|
1018 *sourceX = origoX + mvxVal / 20; |
|
1019 *sourceY = origoY + mvyVal / 20; |
|
1020 |
|
1021 *subpixelX = (mvxVal % 20) != 0; |
|
1022 *subpixelY = (mvyVal % 20) != 0; |
|
1023 |
|
1024 if (mvxVal < 0 && *subpixelX) |
|
1025 *sourceX -= 1; |
|
1026 if (mvyVal < 0 && *subpixelY) |
|
1027 *sourceY -= 1; |
|
1028 } |
|
1029 |
|
1030 |
|
1031 static void blcUVCountRefXY4MVs( |
|
1032 int origoX, int origoY, |
|
1033 int *mvxArray, int *mvyArray, |
|
1034 int *sourceX, int *sourceY, |
|
1035 int *subpixelX, int *subpixelY) |
|
1036 { |
|
1037 int offX, offY; |
|
1038 |
|
1039 blcUVCountMVOffset4MVs(mvxArray, mvyArray, &offX, &offY, subpixelX, subpixelY); |
|
1040 *sourceX = origoX + offX; |
|
1041 *sourceY = origoY + offY; |
|
1042 } |
|
1043 |
|
1044 |
|
1045 /* |
|
1046 * blcYCountRefXY |
|
1047 * |
|
1048 * |
|
1049 * Input parameters: |
|
1050 * mvxVal motion vector components for the block |
|
1051 * mvyVal |
|
1052 * |
|
1053 * destX the coordinates of the destination block |
|
1054 * destY |
|
1055 * |
|
1056 * Output parameters: |
|
1057 * sourceX the absolute position of the source |
|
1058 * sourceY block (may be negative, half-pixel values are |
|
1059 * truncated to the next smaller integer) |
|
1060 * |
|
1061 * subpixelX 1 if half pixel position is used in X direction |
|
1062 * subpixelY 1 if half pixel position is used in Y direction |
|
1063 * |
|
1064 * Function: |
|
1065 * This function counts the absolute position of the luminance source block (and |
|
1066 * sets sourceX, sourceY, subpixelX and subpixelY according to it) when it is |
|
1067 * given the position of the destination block and a motion vector pointing |
|
1068 * to the source block. |
|
1069 * |
|
1070 * Returns: |
|
1071 * See output parameters. |
|
1072 * |
|
1073 * |
|
1074 * |
|
1075 */ |
|
1076 |
|
1077 static void blcYCountRefXY( |
|
1078 int mvxVal, int mvyVal, |
|
1079 int destX, int destY, |
|
1080 int *sourceX, int *sourceY, |
|
1081 int *subpixelX, int *subpixelY) |
|
1082 { |
|
1083 *sourceX = destX + mvxVal / 10; |
|
1084 *sourceY = destY + mvyVal / 10; |
|
1085 |
|
1086 *subpixelX = mvxVal & 1; |
|
1087 *subpixelY = mvyVal & 1; |
|
1088 |
|
1089 if (mvxVal < 0 && *subpixelX) |
|
1090 *sourceX -= 1; |
|
1091 if (mvyVal < 0 && *subpixelY) |
|
1092 *sourceY -= 1; |
|
1093 } |
|
1094 // End of File |
|