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
22OSCL_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
53bool 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
68OSCL_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
128OSCL_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
186OSCL_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