1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 #include <string.h>
19
20 #include "avclib_common.h"
21
InitNeighborAvailability(AVCCommonObj * video,int mbNum)22 OSCL_EXPORT_REF void InitNeighborAvailability(AVCCommonObj *video, int mbNum)
23 {
24 int PicWidthInMbs = video->PicWidthInMbs;
25
26 // do frame-only and postpone intraAvail calculattion
27 video->mbAddrA = mbNum - 1;
28 video->mbAddrB = mbNum - PicWidthInMbs;
29 video->mbAddrC = mbNum - PicWidthInMbs + 1;
30 video->mbAddrD = mbNum - PicWidthInMbs - 1;
31
32 video->mbAvailA = video->mbAvailB = video->mbAvailC = video->mbAvailD = 0;
33 if (video->mb_x)
34 {
35 video->mbAvailA = (video->mblock[video->mbAddrA].slice_id == video->currMB->slice_id);
36 if (video->mb_y)
37 {
38 video->mbAvailD = (video->mblock[video->mbAddrD].slice_id == video->currMB->slice_id);
39 }
40 }
41
42 if (video->mb_y)
43 {
44 video->mbAvailB = (video->mblock[video->mbAddrB].slice_id == video->currMB->slice_id);
45 if (video->mb_x < (PicWidthInMbs - 1))
46 {
47 video->mbAvailC = (video->mblock[video->mbAddrC].slice_id == video->currMB->slice_id);
48 }
49 }
50 return ;
51 }
52
mb_is_available(AVCMacroblock * mblock,uint PicSizeInMbs,int mbAddr,int currMbAddr)53 bool mb_is_available(AVCMacroblock *mblock, uint PicSizeInMbs, int mbAddr, int currMbAddr)
54 {
55 if (mbAddr < 0 || mbAddr >= (int)PicSizeInMbs)
56 {
57 return FALSE;
58 }
59
60 if (mblock[mbAddr].slice_id != mblock[currMbAddr].slice_id)
61 {
62 return FALSE;
63 }
64
65 return TRUE;
66 }
67
predict_nnz(AVCCommonObj * video,int i,int j)68 OSCL_EXPORT_REF int predict_nnz(AVCCommonObj *video, int i, int j)
69 {
70 int pred_nnz = 0;
71 int cnt = 1;
72 AVCMacroblock *tempMB;
73
74 /* left block */
75 /*getLuma4x4Neighbour(video, mb_nr, i, j, -1, 0, &pix);
76 leftMB = video->mblock + pix.mb_addr; */
77 /* replace the above with below (won't work for field decoding), 1/19/04 */
78
79 if (i)
80 {
81 pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1];
82 }
83 else
84 {
85 if (video->mbAvailA)
86 {
87 tempMB = video->mblock + video->mbAddrA;
88 pred_nnz = tempMB->nz_coeff[(j<<2)+3];
89 }
90 else
91 {
92 cnt = 0;
93 }
94 }
95
96
97 /* top block */
98 /*getLuma4x4Neighbour(video, mb_nr, i, j, 0, -1, &pix);
99 topMB = video->mblock + pix.mb_addr;*/
100 /* replace the above with below (won't work for field decoding), 1/19/04 */
101
102 if (j)
103 {
104 pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i];
105 cnt++;
106 }
107 else
108 {
109 if (video->mbAvailB)
110 {
111 tempMB = video->mblock + video->mbAddrB;
112 pred_nnz += tempMB->nz_coeff[12+i];
113 cnt++;
114 }
115 }
116
117
118 if (cnt == 2)
119 {
120 pred_nnz = (pred_nnz + 1) >> 1;
121 }
122
123 return pred_nnz;
124
125 }
126
127
predict_nnz_chroma(AVCCommonObj * video,int i,int j)128 OSCL_EXPORT_REF int predict_nnz_chroma(AVCCommonObj *video, int i, int j)
129 {
130 int pred_nnz = 0;
131 int cnt = 1;
132 AVCMacroblock *tempMB;
133
134 /* left block */
135 /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, -1, 0, &pix);
136 leftMB = video->mblock + pix.mb_addr;*/
137 /* replace the above with below (won't work for field decoding), 1/19/04 */
138 if (i&1)
139 {
140 pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1];
141
142 }
143 else
144 {
145 if (video->mbAvailA)
146 {
147 tempMB = video->mblock + video->mbAddrA;
148 pred_nnz = tempMB->nz_coeff[(j<<2)+i+1];
149 }
150 else
151 {
152 cnt = 0;
153 }
154 }
155
156
157 /* top block */
158 /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, 0, -1, &pix);
159 topMB = video->mblock + pix.mb_addr;*/
160 /* replace the above with below (won't work for field decoding), 1/19/04 */
161
162 if (j&1)
163 {
164 pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i];
165 cnt++;
166 }
167 else
168 {
169 if (video->mbAvailB)
170 {
171 tempMB = video->mblock + video->mbAddrB;
172 pred_nnz += tempMB->nz_coeff[20+i];
173 cnt++;
174 }
175
176 }
177
178 if (cnt == 2)
179 {
180 pred_nnz = (pred_nnz + 1) >> 1;
181 }
182
183 return pred_nnz;
184 }
185
GetMotionVectorPredictor(AVCCommonObj * video,int encFlag)186 OSCL_EXPORT_REF void GetMotionVectorPredictor(AVCCommonObj *video, int encFlag)
187 {
188 AVCMacroblock *currMB = video->currMB;
189 AVCMacroblock *MB_A, *MB_B, *MB_C, *MB_D;
190 int block_x, block_y, block_x_1, block_y_1, new_block_x;
191 int mbPartIdx, subMbPartIdx, offset_indx;
192 int16 *mv, pmv_x, pmv_y;
193 int nmSubMbHeight, nmSubMbWidth, mbPartIdx_X, mbPartIdx_Y;
194 int avail_a, avail_b, avail_c;
195 const static uint32 C = 0x5750;
196 int i, j, offset_MbPart_indx, refIdxLXA, refIdxLXB, refIdxLXC = 0, curr_ref_idx;
197 int pmv_A_x, pmv_B_x, pmv_C_x = 0, pmv_A_y, pmv_B_y, pmv_C_y = 0;
198
199 /* we have to take care of Intra/skip blocks somewhere, i.e. set MV to 0 and set ref to -1! */
200 /* we have to populate refIdx as well */
201
202
203 MB_A = &video->mblock[video->mbAddrA];
204 MB_B = &video->mblock[video->mbAddrB];
205
206
207 if (currMB->mbMode == AVC_SKIP /* && !encFlag */) /* only for decoder */
208 {
209 currMB->ref_idx_L0[0] = currMB->ref_idx_L0[1] = currMB->ref_idx_L0[2] = currMB->ref_idx_L0[3] = 0;
210 if (video->mbAvailA && video->mbAvailB)
211 {
212 if ((MB_A->ref_idx_L0[1] == 0 && MB_A->mvL0[3] == 0) ||
213 (MB_B->ref_idx_L0[2] == 0 && MB_B->mvL0[12] == 0))
214 {
215 memset(currMB->mvL0, 0, sizeof(int32)*16);
216 return;
217 }
218 }
219 else
220 {
221 memset(currMB->mvL0, 0, sizeof(int32)*16);
222 return;
223 }
224 video->mvd_l0[0][0][0] = 0;
225 video->mvd_l0[0][0][1] = 0;
226 }
227
228 MB_C = &video->mblock[video->mbAddrC];
229 MB_D = &video->mblock[video->mbAddrD];
230
231 offset_MbPart_indx = 0;
232 for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
233 {
234 offset_indx = 0;
235 nmSubMbHeight = currMB->SubMbPartHeight[mbPartIdx] >> 2;
236 nmSubMbWidth = currMB->SubMbPartWidth[mbPartIdx] >> 2;
237 mbPartIdx_X = ((mbPartIdx + offset_MbPart_indx) & 1) << 1;
238 mbPartIdx_Y = (mbPartIdx + offset_MbPart_indx) & 2;
239
240 for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
241 {
242 block_x = mbPartIdx_X + ((subMbPartIdx + offset_indx) & 1);
243 block_y = mbPartIdx_Y + (((subMbPartIdx + offset_indx) >> 1) & 1);
244
245 block_x_1 = block_x - 1;
246 block_y_1 = block_y - 1;
247 refIdxLXA = refIdxLXB = refIdxLXC = -1;
248 pmv_A_x = pmv_A_y = pmv_B_x = pmv_B_y = pmv_C_x = pmv_C_y = 0;
249
250 if (block_x)
251 {
252 avail_a = 1;
253 refIdxLXA = currMB->ref_idx_L0[(block_y & 2) + (block_x_1 >> 1)];
254 mv = (int16*)(currMB->mvL0 + (block_y << 2) + block_x_1);
255 pmv_A_x = *mv++;
256 pmv_A_y = *mv;
257 }
258 else
259 {
260 avail_a = video->mbAvailA;
261 if (avail_a)
262 {
263 refIdxLXA = MB_A->ref_idx_L0[(block_y & 2) + 1];
264 mv = (int16*)(MB_A->mvL0 + (block_y << 2) + 3);
265 pmv_A_x = *mv++;
266 pmv_A_y = *mv;
267 }
268 }
269
270 if (block_y)
271 {
272 avail_b = 1;
273 refIdxLXB = currMB->ref_idx_L0[(block_y_1 & 2) + (block_x >> 1)];
274 mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x);
275 pmv_B_x = *mv++;
276 pmv_B_y = *mv;
277 }
278
279 else
280 {
281 avail_b = video->mbAvailB;
282 if (avail_b)
283 {
284 refIdxLXB = MB_B->ref_idx_L0[2 + (block_x >> 1)];
285 mv = (int16*)(MB_B->mvL0 + 12 + block_x);
286 pmv_B_x = *mv++;
287 pmv_B_y = *mv;
288 }
289 }
290
291 new_block_x = block_x + (currMB->SubMbPartWidth[mbPartIdx] >> 2) - 1;
292 avail_c = (C >> ((block_y << 2) + new_block_x)) & 0x1;
293
294 if (avail_c)
295 {
296 /* it guaranteed that block_y > 0 && new_block_x<3 ) */
297 refIdxLXC = currMB->ref_idx_L0[(block_y_1 & 2) + ((new_block_x+1) >> 1)];
298 mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + (new_block_x + 1));
299 pmv_C_x = *mv++;
300 pmv_C_y = *mv;
301 }
302 else
303 {
304 if (block_y == 0 && new_block_x < 3)
305 {
306 avail_c = video->mbAvailB;
307 if (avail_c)
308 {
309 refIdxLXC = MB_B->ref_idx_L0[2 + ((new_block_x+1)>>1)];
310 mv = (int16*)(MB_B->mvL0 + 12 + (new_block_x + 1));
311 pmv_C_x = *mv++;
312 pmv_C_y = *mv;
313 }
314 }
315 else if (block_y == 0 && new_block_x == 3)
316 {
317 avail_c = video->mbAvailC;
318 if (avail_c)
319 {
320 refIdxLXC = MB_C->ref_idx_L0[2];
321 mv = (int16*)(MB_C->mvL0 + 12);
322 pmv_C_x = *mv++;
323 pmv_C_y = *mv;
324 }
325 }
326
327 if (avail_c == 0)
328 { /* check D */
329 if (block_x && block_y)
330 {
331 avail_c = 1;
332 refIdxLXC = currMB->ref_idx_L0[(block_y_1 & 2) + (block_x_1 >> 1)];
333 mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x_1);
334 pmv_C_x = *mv++;
335 pmv_C_y = *mv;
336 }
337 else if (block_y)
338 {
339 avail_c = video->mbAvailA;
340 if (avail_c)
341 {
342 refIdxLXC = MB_A->ref_idx_L0[(block_y_1 & 2) + 1];
343 mv = (int16*)(MB_A->mvL0 + (block_y_1 << 2) + 3);
344 pmv_C_x = *mv++;
345 pmv_C_y = *mv;
346 }
347 }
348 else if (block_x)
349 {
350 avail_c = video->mbAvailB;
351 if (avail_c)
352 {
353 refIdxLXC = MB_B->ref_idx_L0[2 + (block_x_1 >> 1)];
354 mv = (int16*)(MB_B->mvL0 + 12 + block_x_1);
355 pmv_C_x = *mv++;
356 pmv_C_y = *mv;
357 }
358 }
359 else
360 {
361 avail_c = video->mbAvailD;
362 if (avail_c)
363 {
364 refIdxLXC = MB_D->ref_idx_L0[3];
365 mv = (int16*)(MB_D->mvL0 + 15);
366 pmv_C_x = *mv++;
367 pmv_C_y = *mv;
368 }
369 }
370 }
371 }
372
373 offset_indx = currMB->SubMbPartWidth[mbPartIdx] >> 3;
374
375 curr_ref_idx = currMB->ref_idx_L0[(block_y & 2) + (block_x >> 1)];
376
377 if (avail_a && !(avail_b || avail_c))
378 {
379 pmv_x = pmv_A_x;
380 pmv_y = pmv_A_y;
381 }
382 else if (((curr_ref_idx == refIdxLXA) + (curr_ref_idx == refIdxLXB) + (curr_ref_idx == refIdxLXC)) == 1)
383 {
384 if (curr_ref_idx == refIdxLXA)
385 {
386 pmv_x = pmv_A_x;
387 pmv_y = pmv_A_y;
388 }
389 else if (curr_ref_idx == refIdxLXB)
390 {
391 pmv_x = pmv_B_x;
392 pmv_y = pmv_B_y;
393 }
394 else
395 {
396 pmv_x = pmv_C_x;
397 pmv_y = pmv_C_y;
398 }
399 }
400 else
401 {
402 pmv_x = AVC_MEDIAN(pmv_A_x, pmv_B_x, pmv_C_x);
403 pmv_y = AVC_MEDIAN(pmv_A_y, pmv_B_y, pmv_C_y);
404 }
405
406 /* overwrite if special case */
407 if (currMB->NumMbPart == 2)
408 {
409 if (currMB->MbPartWidth == 16)
410 {
411 if (mbPartIdx == 0)
412 {
413 if (refIdxLXB == curr_ref_idx)
414 {
415 pmv_x = pmv_B_x;
416 pmv_y = pmv_B_y;
417 }
418 }
419 else if (refIdxLXA == curr_ref_idx)
420 {
421 pmv_x = pmv_A_x;
422 pmv_y = pmv_A_y;
423 }
424 }
425 else
426 {
427 if (mbPartIdx == 0)
428 {
429 if (refIdxLXA == curr_ref_idx)
430 {
431 pmv_x = pmv_A_x;
432 pmv_y = pmv_A_y;
433 }
434 }
435 else if (refIdxLXC == curr_ref_idx)
436 {
437 pmv_x = pmv_C_x;
438 pmv_y = pmv_C_y;
439 }
440 }
441 }
442
443 mv = (int16*)(currMB->mvL0 + block_x + (block_y << 2));
444
445 if (encFlag) /* calculate residual MV video->mvd_l0 */
446 {
447 video->mvd_l0[mbPartIdx][subMbPartIdx][0] = *mv++ - pmv_x;
448 video->mvd_l0[mbPartIdx][subMbPartIdx][1] = *mv++ - pmv_y;
449 }
450 else /* calculate original MV currMB->mvL0 */
451 {
452 pmv_x += video->mvd_l0[mbPartIdx][subMbPartIdx][0];
453 pmv_y += video->mvd_l0[mbPartIdx][subMbPartIdx][1];
454
455 for (i = 0; i < nmSubMbHeight; i++)
456 {
457 for (j = 0; j < nmSubMbWidth; j++)
458 {
459 *mv++ = pmv_x;
460 *mv++ = pmv_y;
461 }
462 mv += (8 - (j << 1));
463 }
464 }
465 }
466 offset_MbPart_indx = currMB->MbPartWidth >> 4;
467
468 }
469 }
470
471
472