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