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