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 "avcenc_lib.h"
19
20
21AVCEnc_Status AVCEncodeSlice(AVCEncObject *encvid)
22{
23    AVCEnc_Status status = AVCENC_SUCCESS;
24    AVCCommonObj *video = encvid->common;
25    AVCPicParamSet *pps = video->currPicParams;
26    AVCSliceHeader *sliceHdr = video->sliceHdr;
27    AVCMacroblock *currMB ;
28    AVCEncBitstream *stream = encvid->bitstream;
29    uint slice_group_id;
30    int CurrMbAddr, slice_type;
31
32    slice_type = video->slice_type;
33
34    /* set the first mb in slice */
35    video->mbNum = CurrMbAddr = sliceHdr->first_mb_in_slice;// * (1+video->MbaffFrameFlag);
36    slice_group_id = video->MbToSliceGroupMap[CurrMbAddr];
37
38    video->mb_skip_run = 0;
39
40    /* while loop , see subclause 7.3.4 */
41    while (1)
42    {
43        video->mbNum = CurrMbAddr;
44        currMB = video->currMB = &(video->mblock[CurrMbAddr]);
45        currMB->slice_id = video->slice_id;  // for deblocking
46
47        video->mb_x = CurrMbAddr % video->PicWidthInMbs;
48        video->mb_y = CurrMbAddr / video->PicWidthInMbs;
49
50        /* initialize QP for this MB here*/
51        /* calculate currMB->QPy */
52        RCInitMBQP(encvid);
53
54        /* check the availability of neighboring macroblocks */
55        InitNeighborAvailability(video, CurrMbAddr);
56
57        /* Assuming that InitNeighborAvailability has been called prior to this function */
58        video->intraAvailA = video->intraAvailB = video->intraAvailC = video->intraAvailD = 0;
59        /* this is necessary for all subsequent intra search */
60
61        if (!video->currPicParams->constrained_intra_pred_flag)
62        {
63            video->intraAvailA = video->mbAvailA;
64            video->intraAvailB = video->mbAvailB;
65            video->intraAvailC = video->mbAvailC;
66            video->intraAvailD = video->mbAvailD;
67        }
68        else
69        {
70            if (video->mbAvailA)
71            {
72                video->intraAvailA = video->mblock[video->mbAddrA].mb_intra;
73            }
74            if (video->mbAvailB)
75            {
76                video->intraAvailB = video->mblock[video->mbAddrB].mb_intra ;
77            }
78            if (video->mbAvailC)
79            {
80                video->intraAvailC = video->mblock[video->mbAddrC].mb_intra;
81            }
82            if (video->mbAvailD)
83            {
84                video->intraAvailD = video->mblock[video->mbAddrD].mb_intra;
85            }
86        }
87
88        /* encode_one_macroblock() */
89        status = EncodeMB(encvid);
90        if (status != AVCENC_SUCCESS)
91        {
92            break;
93        }
94
95        /* go to next MB */
96        CurrMbAddr++;
97
98        while ((uint)video->MbToSliceGroupMap[CurrMbAddr] != slice_group_id &&
99                (uint)CurrMbAddr < video->PicSizeInMbs)
100        {
101            CurrMbAddr++;
102        }
103
104        if ((uint)CurrMbAddr >= video->PicSizeInMbs)
105        {
106            /* end of slice, return, but before that check to see if there are other slices
107            to be encoded. */
108            encvid->currSliceGroup++;
109            if (encvid->currSliceGroup > (int)pps->num_slice_groups_minus1) /* no more slice group */
110            {
111                status = AVCENC_PICTURE_READY;
112                break;
113            }
114            else
115            {
116                /* find first_mb_num for the next slice */
117                CurrMbAddr = 0;
118                while (video->MbToSliceGroupMap[CurrMbAddr] != encvid->currSliceGroup &&
119                        (uint)CurrMbAddr < video->PicSizeInMbs)
120                {
121                    CurrMbAddr++;
122                }
123                if ((uint)CurrMbAddr >= video->PicSizeInMbs)
124                {
125                    status = AVCENC_SLICE_EMPTY; /* error, one slice group has no MBs in it */
126                }
127
128                video->mbNum = CurrMbAddr;
129                status = AVCENC_SUCCESS;
130                break;
131            }
132        }
133    }
134
135    if (video->mb_skip_run > 0)
136    {
137        /* write skip_run */
138        if (slice_type != AVC_I_SLICE && slice_type != AVC_SI_SLICE)
139        {
140            ue_v(stream, video->mb_skip_run);
141            video->mb_skip_run = 0;
142        }
143        else    /* shouldn't happen */
144        {
145            status = AVCENC_FAIL;
146        }
147    }
148
149    return status;
150}
151
152
153AVCEnc_Status EncodeMB(AVCEncObject *encvid)
154{
155    AVCEnc_Status status = AVCENC_SUCCESS;
156    AVCCommonObj *video = encvid->common;
157    AVCPictureData *currPic = video->currPic;
158    AVCFrameIO  *currInput = encvid->currInput;
159    AVCMacroblock *currMB = video->currMB;
160    AVCMacroblock *MB_A, *MB_B;
161    AVCEncBitstream *stream = encvid->bitstream;
162    AVCRateControl *rateCtrl = encvid->rateCtrl;
163    uint8 *cur, *curL, *curCb, *curCr;
164    uint8 *orgL, *orgCb, *orgCr, *org4;
165    int CurrMbAddr = video->mbNum;
166    int picPitch = currPic->pitch;
167    int orgPitch = currInput->pitch;
168    int x_position = (video->mb_x << 4);
169    int y_position = (video->mb_y << 4);
170    int offset;
171    int b8, b4, blkidx;
172    AVCResidualType  resType;
173    int slice_type;
174    int numcoeff; /* output from residual_block_cavlc */
175    int cost16, cost8;
176
177    int num_bits, start_mb_bits, start_text_bits;
178
179    slice_type = video->slice_type;
180
181    /* now, point to the reconstructed frame */
182    offset = y_position * picPitch + x_position;
183    curL = currPic->Sl + offset;
184    orgL = currInput->YCbCr[0] + offset;
185    offset = (offset + x_position) >> 2;
186    curCb = currPic->Scb + offset;
187    curCr = currPic->Scr + offset;
188    orgCb = currInput->YCbCr[1] + offset;
189    orgCr = currInput->YCbCr[2] + offset;
190
191    if (orgPitch != picPitch)
192    {
193        offset = y_position * (orgPitch - picPitch);
194        orgL += offset;
195        offset >>= 2;
196        orgCb += offset;
197        orgCr += offset;
198    }
199
200    /******* determine MB prediction mode *******/
201    if (encvid->intraSearch[CurrMbAddr])
202    {
203        MBIntraSearch(encvid, CurrMbAddr, curL, picPitch);
204    }
205    /******* This part should be determined somehow ***************/
206    if (currMB->mbMode == AVC_I_PCM)
207    {
208        /* write down mb_type and PCM data */
209        /* and copy from currInput to currPic */
210        status = EncodeIntraPCM(encvid);
211
212
213        return status;
214    }
215
216    /****** for intra prediction, pred is already done *******/
217    /****** for I4, the recon is ready and Xfrm coefs are ready to be encoded *****/
218
219    //RCCalculateMAD(encvid,currMB,orgL,orgPitch); // no need to re-calculate MAD for Intra
220    // not used since totalSAD is used instead
221
222    /* compute the prediction */
223    /* output is video->pred_block */
224    if (!currMB->mb_intra)
225    {
226        AVCMBMotionComp(encvid, video); /* perform prediction and residue calculation */
227        /* we can do the loop here and call dct_luma */
228        video->pred_pitch = picPitch;
229        currMB->CBP = 0;
230        cost16 = 0;
231        cur = curL;
232        org4 = orgL;
233
234        for (b8 = 0; b8 < 4; b8++)
235        {
236            cost8 = 0;
237
238            for (b4 = 0; b4 < 4; b4++)
239            {
240                blkidx = blkIdx2blkXY[b8][b4];
241                video->pred_block = cur;
242                numcoeff = dct_luma(encvid, blkidx, cur, org4, &cost8);
243                currMB->nz_coeff[blkidx] = numcoeff;
244                if (numcoeff)
245                {
246                    video->cbp4x4 |= (1 << blkidx);
247                    currMB->CBP |= (1 << b8);
248                }
249
250                if (b4&1)
251                {
252                    cur += ((picPitch << 2) - 4);
253                    org4 += ((orgPitch << 2) - 4);
254                }
255                else
256                {
257                    cur += 4;
258                    org4 += 4;
259                }
260            }
261
262            /* move the IDCT part out of dct_luma to accommodate the check
263               for coeff_cost. */
264
265            if ((currMB->CBP&(1 << b8)) && (cost8 <= _LUMA_COEFF_COST_))
266            {
267                cost8 = 0; // reset it
268
269                currMB->CBP ^= (1 << b8);
270                blkidx = blkIdx2blkXY[b8][0];
271
272                currMB->nz_coeff[blkidx] = 0;
273                currMB->nz_coeff[blkidx+1] = 0;
274                currMB->nz_coeff[blkidx+4] = 0;
275                currMB->nz_coeff[blkidx+5] = 0;
276            }
277
278            cost16 += cost8;
279
280            if (b8&1)
281            {
282                cur -= 8;
283                org4 -= 8;
284            }
285            else
286            {
287                cur += (8 - (picPitch << 3));
288                org4 += (8 - (orgPitch << 3));
289            }
290        }
291
292        /* after the whole MB, we do another check for coeff_cost */
293        if ((currMB->CBP&0xF) && (cost16 <= _LUMA_MB_COEFF_COST_))
294        {
295            currMB->CBP = 0;  // reset it to zero
296            memset(currMB->nz_coeff, 0, sizeof(uint8)*16);
297        }
298
299        // now we do IDCT
300        MBInterIdct(video, curL, currMB, picPitch);
301
302//      video->pred_block = video->pred + 256;
303    }
304    else    /* Intra prediction */
305    {
306        encvid->numIntraMB++;
307
308        if (currMB->mbMode == AVC_I16) /* do prediction for the whole macroblock */
309        {
310            currMB->CBP = 0;
311            /* get the prediction from encvid->pred_i16 */
312            dct_luma_16x16(encvid, curL, orgL);
313        }
314        video->pred_block = encvid->pred_ic[currMB->intra_chroma_pred_mode];
315    }
316
317    /* chrominance */
318    /* not need to do anything, the result is in encvid->pred_ic
319    chroma dct must be aware that prediction block can come from either intra or inter. */
320
321    dct_chroma(encvid, curCb, orgCb, 0);
322
323    dct_chroma(encvid, curCr, orgCr, 1);
324
325
326    /* 4.1 if there's nothing in there, video->mb_skip_run++ */
327    /* 4.2 if coded, check if there is a run of skipped MB, encodes it,
328            set video->QPyprev = currMB->QPy; */
329
330    /* 5. vlc encode */
331
332    /* check for skipped macroblock, INTER only */
333    if (!currMB->mb_intra)
334    {
335        /* decide whether this MB (for inter MB) should be skipped if there's nothing left. */
336        if (!currMB->CBP && currMB->NumMbPart == 1 && currMB->QPy == video->QPy)
337        {
338            if (currMB->MBPartPredMode[0][0] == AVC_Pred_L0 && currMB->ref_idx_L0[0] == 0)
339            {
340                MB_A = &video->mblock[video->mbAddrA];
341                MB_B = &video->mblock[video->mbAddrB];
342
343                if (!video->mbAvailA || !video->mbAvailB)
344                {
345                    if (currMB->mvL0[0] == 0) /* both mv components are zeros.*/
346                    {
347                        currMB->mbMode = AVC_SKIP;
348                        video->mvd_l0[0][0][0] = 0;
349                        video->mvd_l0[0][0][1] = 0;
350                    }
351                }
352                else
353                {
354                    if ((MB_A->ref_idx_L0[1] == 0 && MB_A->mvL0[3] == 0) ||
355                            (MB_B->ref_idx_L0[2] == 0 && MB_B->mvL0[12] == 0))
356                    {
357                        if (currMB->mvL0[0] == 0) /* both mv components are zeros.*/
358                        {
359                            currMB->mbMode = AVC_SKIP;
360                            video->mvd_l0[0][0][0] = 0;
361                            video->mvd_l0[0][0][1] = 0;
362                        }
363                    }
364                    else if (video->mvd_l0[0][0][0] == 0 && video->mvd_l0[0][0][1] == 0)
365                    {
366                        currMB->mbMode = AVC_SKIP;
367                    }
368                }
369            }
370
371            if (currMB->mbMode == AVC_SKIP)
372            {
373                video->mb_skip_run++;
374
375                /* set parameters */
376                /* not sure whether we need the followings */
377                if (slice_type == AVC_P_SLICE)
378                {
379                    currMB->mbMode = AVC_SKIP;
380                    currMB->MbPartWidth = currMB->MbPartHeight = 16;
381                    currMB->MBPartPredMode[0][0] = AVC_Pred_L0;
382                    currMB->NumMbPart = 1;
383                    currMB->NumSubMbPart[0] = currMB->NumSubMbPart[1] =
384                                                  currMB->NumSubMbPart[2] = currMB->NumSubMbPart[3] = 1;
385                    currMB->SubMbPartWidth[0] = currMB->SubMbPartWidth[1] =
386                                                    currMB->SubMbPartWidth[2] = currMB->SubMbPartWidth[3] = currMB->MbPartWidth;
387                    currMB->SubMbPartHeight[0] = currMB->SubMbPartHeight[1] =
388                                                     currMB->SubMbPartHeight[2] = currMB->SubMbPartHeight[3] = currMB->MbPartHeight;
389
390                }
391                else if (slice_type == AVC_B_SLICE)
392                {
393                    currMB->mbMode = AVC_SKIP;
394                    currMB->MbPartWidth = currMB->MbPartHeight = 8;
395                    currMB->MBPartPredMode[0][0] = AVC_Direct;
396                    currMB->NumMbPart = -1;
397                }
398
399                /* for skipped MB, always look at the first entry in RefPicList */
400                currMB->RefIdx[0] = currMB->RefIdx[1] =
401                                        currMB->RefIdx[2] = currMB->RefIdx[3] = video->RefPicList0[0]->RefIdx;
402
403                /* do not return yet, need to do some copies */
404            }
405        }
406    }
407    /* non-skipped MB */
408
409
410    /************* START ENTROPY CODING *************************/
411
412    start_mb_bits = 32 + (encvid->bitstream->write_pos << 3) - encvid->bitstream->bit_left;
413
414    /* encode mb_type, mb_pred, sub_mb_pred, CBP */
415    if (slice_type != AVC_I_SLICE && slice_type != AVC_SI_SLICE && currMB->mbMode != AVC_SKIP)
416    {
417        //if(!pps->entropy_coding_mode_flag)  ALWAYS true
418        {
419            ue_v(stream, video->mb_skip_run);
420            video->mb_skip_run = 0;
421        }
422    }
423
424    if (currMB->mbMode != AVC_SKIP)
425    {
426        status = EncodeMBHeader(currMB, encvid);
427        if (status != AVCENC_SUCCESS)
428        {
429            return status;
430        }
431    }
432
433    start_text_bits = 32 + (encvid->bitstream->write_pos << 3) - encvid->bitstream->bit_left;
434
435    /**** now decoding part *******/
436    resType = AVC_Luma;
437
438    /* DC transform for luma I16 mode */
439    if (currMB->mbMode == AVC_I16)
440    {
441        /* vlc encode level/run */
442        status = enc_residual_block(encvid, AVC_Intra16DC, encvid->numcoefdc, currMB);
443        if (status != AVCENC_SUCCESS)
444        {
445            return status;
446        }
447        resType = AVC_Intra16AC;
448    }
449
450    /* VLC encoding for luma */
451    for (b8 = 0; b8 < 4; b8++)
452    {
453        if (currMB->CBP&(1 << b8))
454        {
455            for (b4 = 0; b4 < 4; b4++)
456            {
457                /* vlc encode level/run */
458                status = enc_residual_block(encvid, resType, (b8 << 2) + b4, currMB);
459                if (status != AVCENC_SUCCESS)
460                {
461                    return status;
462                }
463            }
464        }
465    }
466
467    /* chroma */
468    if (currMB->CBP & (3 << 4)) /* chroma DC residual present */
469    {
470        for (b8 = 0; b8 < 2; b8++) /* for iCbCr */
471        {
472            /* vlc encode level/run */
473            status = enc_residual_block(encvid, AVC_ChromaDC, encvid->numcoefcdc[b8] + (b8 << 3), currMB);
474            if (status != AVCENC_SUCCESS)
475            {
476                return status;
477            }
478        }
479    }
480
481    if (currMB->CBP & (2 << 4))
482    {
483        /* AC part */
484        for (b8 = 0; b8 < 2; b8++) /* for iCbCr */
485        {
486            for (b4 = 0; b4 < 4; b4++)  /* for each block inside Cb or Cr */
487            {
488                /* vlc encode level/run */
489                status = enc_residual_block(encvid, AVC_ChromaAC, 16 + (b8 << 2) + b4, currMB);
490                if (status != AVCENC_SUCCESS)
491                {
492                    return status;
493                }
494            }
495        }
496    }
497
498
499    num_bits = 32 + (encvid->bitstream->write_pos << 3) - encvid->bitstream->bit_left;
500
501    RCPostMB(video, rateCtrl, start_text_bits - start_mb_bits,
502             num_bits - start_text_bits);
503
504//  num_bits -= start_mb_bits;
505//  fprintf(fdebug,"MB #%d: %d bits\n",CurrMbAddr,num_bits);
506//  fclose(fdebug);
507    return status;
508}
509
510/* copy the content from predBlock back to the reconstructed YUV frame */
511void Copy_MB(uint8 *curL, uint8 *curCb, uint8 *curCr, uint8 *predBlock, int picPitch)
512{
513    int j, offset;
514    uint32 *dst, *dst2, *src;
515
516    dst = (uint32*)curL;
517    src = (uint32*)predBlock;
518
519    offset = (picPitch - 16) >> 2;
520
521    for (j = 0; j < 16; j++)
522    {
523        *dst++ = *src++;
524        *dst++ = *src++;
525        *dst++ = *src++;
526        *dst++ = *src++;
527
528        dst += offset;
529    }
530
531    dst = (uint32*)curCb;
532    dst2 = (uint32*)curCr;
533    offset >>= 1;
534
535    for (j = 0; j < 8; j++)
536    {
537        *dst++ = *src++;
538        *dst++ = *src++;
539        *dst2++ = *src++;
540        *dst2++ = *src++;
541
542        dst += offset;
543        dst2 += offset;
544    }
545    return ;
546}
547
548/* encode mb_type, mb_pred, sub_mb_pred, CBP */
549/* decide whether this MB (for inter MB) should be skipped */
550AVCEnc_Status EncodeMBHeader(AVCMacroblock *currMB, AVCEncObject *encvid)
551{
552    AVCEnc_Status status = AVCENC_SUCCESS;
553    uint mb_type;
554    AVCCommonObj *video = encvid->common;
555    AVCEncBitstream *stream = encvid->bitstream;
556
557    if (currMB->CBP > 47)   /* chroma CBP is 11 */
558    {
559        currMB->CBP -= 16;  /* remove the 5th bit from the right */
560    }
561
562    mb_type = InterpretMBType(currMB, video->slice_type);
563
564    status = ue_v(stream, mb_type);
565
566    if (currMB->mbMode == AVC_P8 || currMB->mbMode == AVC_P8ref0)
567    {
568        status = sub_mb_pred(video, currMB, stream);
569    }
570    else
571    {
572        status = mb_pred(video, currMB, stream) ;
573    }
574
575    if (currMB->mbMode != AVC_I16)
576    {
577        /* decode coded_block_pattern */
578        status = EncodeCBP(currMB, stream);
579    }
580
581    /* calculate currMB->mb_qp_delta = currMB->QPy - video->QPyprev */
582    if (currMB->CBP > 0 || currMB->mbMode == AVC_I16)
583    {
584        status = se_v(stream, currMB->QPy - video->QPy);
585        video->QPy = currMB->QPy; /* = (video->QPyprev + currMB->mb_qp_delta + 52)%52; */
586        // no need video->QPc = currMB->QPc;
587    }
588    else
589    {
590        if (currMB->QPy != video->QPy) // current QP is not the same as previous QP
591        {
592            /* restore these values */
593            RCRestoreQP(currMB, video, encvid);
594        }
595    }
596
597    return status;
598}
599
600
601/* inputs are mbMode, mb_intra, i16Mode, CBP, NumMbPart, MbPartWidth, MbPartHeight */
602uint InterpretMBType(AVCMacroblock *currMB, int slice_type)
603{
604    int CBP_chrom;
605    int mb_type;// part1, part2, part3;
606//  const static int MapParts2Type[2][3][3]={{{4,8,12},{10,6,14},{16,18,20}},
607//  {{5,9,13},{11,7,15},{17,19,21}}};
608
609    if (currMB->mb_intra)
610    {
611        if (currMB->mbMode == AVC_I4)
612        {
613            mb_type = 0;
614        }
615        else if (currMB->mbMode == AVC_I16)
616        {
617            CBP_chrom = (currMB->CBP & 0x30);
618            if (currMB->CBP&0xF)
619            {
620                currMB->CBP |= 0xF;  /* either 0x0 or 0xF */
621                mb_type = 13;
622            }
623            else
624            {
625                mb_type = 1;
626            }
627            mb_type += (CBP_chrom >> 2) + currMB->i16Mode;
628        }
629        else /* if(currMB->mbMode == AVC_I_PCM) */
630        {
631            mb_type = 25;
632        }
633    }
634    else
635    {  /* P-MB *//* note that the order of the enum AVCMBMode cannot be changed
636        since we use it here. */
637        mb_type = currMB->mbMode - AVC_P16;
638    }
639
640    if (slice_type == AVC_P_SLICE)
641    {
642        if (currMB->mb_intra)
643        {
644            mb_type += 5;
645        }
646    }
647    // following codes have not been tested yet, not needed.
648    /*  else if(slice_type == AVC_B_SLICE)
649        {
650            if(currMB->mbMode == AVC_BDirect16)
651            {
652                mb_type = 0;
653            }
654            else if(currMB->mbMode == AVC_P16)
655            {
656                mb_type = currMB->MBPartPredMode[0][0] + 1; // 1 or 2
657            }
658            else if(currMB->mbMode == AVC_P8)
659            {
660                mb_type = 26;
661            }
662            else if(currMB->mbMode == AVC_P8ref0)
663            {
664                mb_type = 27;
665            }
666            else
667            {
668                part1 = currMB->mbMode - AVC_P16x8;
669                part2 = currMB->MBPartPredMode[0][0];
670                part3 = currMB->MBPartPredMode[1][0];
671                mb_type = MapParts2Type[part1][part2][part3];
672            }
673        }
674
675        if(slice_type == AVC_SI_SLICE)
676        {
677            mb_type++;
678        }
679    */
680    return (uint)mb_type;
681}
682
683//const static int mbPart2raster[3][4] = {{0,0,0,0},{1,1,0,0},{1,0,1,0}};
684
685/* see subclause 7.3.5.1 */
686AVCEnc_Status mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream)
687{
688    AVCEnc_Status status = AVCENC_SUCCESS;
689    int mbPartIdx;
690    AVCSliceHeader *sliceHdr = video->sliceHdr;
691    int max_ref_idx;
692    uint code;
693
694    if (currMB->mbMode == AVC_I4 || currMB->mbMode == AVC_I16)
695    {
696        if (currMB->mbMode == AVC_I4)
697        {
698            /* perform prediction to get the actual intra 4x4 pred mode */
699            EncodeIntra4x4Mode(video, currMB, stream);
700            /* output will be in currMB->i4Mode[4][4] */
701        }
702
703        /* assume already set from MBPrediction() */
704        status = ue_v(stream, currMB->intra_chroma_pred_mode);
705    }
706    else if (currMB->MBPartPredMode[0][0] != AVC_Direct)
707    {
708
709        memset(currMB->ref_idx_L0, 0, sizeof(int16)*4);
710
711        /* see subclause 7.4.5.1 for the range of ref_idx_lX */
712        max_ref_idx = sliceHdr->num_ref_idx_l0_active_minus1;
713        /*      if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
714                    max_ref_idx = 2*sliceHdr->num_ref_idx_l0_active_minus1 + 1;
715        */
716        /* decode ref index for L0 */
717        if (sliceHdr->num_ref_idx_l0_active_minus1 > 0)
718        {
719            for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
720            {
721                if (/*(sliceHdr->num_ref_idx_l0_active_minus1>0 || currMB->mb_field_decoding_flag) &&*/
722                    currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
723                {
724                    code = currMB->ref_idx_L0[mbPartIdx];
725                    status = te_v(stream, code, max_ref_idx);
726                }
727            }
728        }
729
730        /* see subclause 7.4.5.1 for the range of ref_idx_lX */
731        max_ref_idx = sliceHdr->num_ref_idx_l1_active_minus1;
732        /*      if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
733                    max_ref_idx = 2*sliceHdr->num_ref_idx_l1_active_minus1 + 1;
734        */
735        /* decode ref index for L1 */
736        if (sliceHdr->num_ref_idx_l1_active_minus1 > 0)
737        {
738            for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
739            {
740                if (/*(sliceHdr->num_ref_idx_l1_active_minus1>0 || currMB->mb_field_decoding_flag) &&*/
741                    currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
742                {
743                    status = te_v(stream, currMB->ref_idx_L1[mbPartIdx], max_ref_idx);
744                }
745            }
746        }
747
748        /* encode mvd_l0 */
749        for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
750        {
751            if (currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
752            {
753                status = se_v(stream, video->mvd_l0[mbPartIdx][0][0]);
754                status = se_v(stream, video->mvd_l0[mbPartIdx][0][1]);
755            }
756        }
757        /* encode mvd_l1 */
758        for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
759        {
760            if (currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
761            {
762                status = se_v(stream, video->mvd_l1[mbPartIdx][0][0]);
763                status = se_v(stream, video->mvd_l1[mbPartIdx][0][1]);
764            }
765        }
766    }
767
768    return status;
769}
770
771/* see subclause 7.3.5.2 */
772AVCEnc_Status sub_mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream)
773{
774    AVCEnc_Status status = AVCENC_SUCCESS;
775    int mbPartIdx, subMbPartIdx;
776    AVCSliceHeader *sliceHdr = video->sliceHdr;
777    uint max_ref_idx;
778    uint slice_type = video->slice_type;
779    uint sub_mb_type[4];
780
781    /* this should move somewhere else where we don't have to make this check */
782    if (currMB->mbMode == AVC_P8ref0)
783    {
784        memset(currMB->ref_idx_L0, 0, sizeof(int16)*4);
785    }
786
787    /* we have to check the values to make sure they are valid  */
788    /* assign values to currMB->sub_mb_type[] */
789    if (slice_type == AVC_P_SLICE)
790    {
791        InterpretSubMBTypeP(currMB, sub_mb_type);
792    }
793    /* no need to check for B-slice
794        else if(slice_type == AVC_B_SLICE)
795        {
796            InterpretSubMBTypeB(currMB,sub_mb_type);
797        }*/
798
799    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
800    {
801        status = ue_v(stream, sub_mb_type[mbPartIdx]);
802    }
803
804    /* see subclause 7.4.5.1 for the range of ref_idx_lX */
805    max_ref_idx = sliceHdr->num_ref_idx_l0_active_minus1;
806    /*  if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
807            max_ref_idx = 2*sliceHdr->num_ref_idx_l0_active_minus1 + 1; */
808
809    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
810    {
811        if ((sliceHdr->num_ref_idx_l0_active_minus1 > 0 /*|| currMB->mb_field_decoding_flag*/) &&
812                currMB->mbMode != AVC_P8ref0 && /*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
813                currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
814        {
815            status = te_v(stream, currMB->ref_idx_L0[mbPartIdx], max_ref_idx);
816        }
817        /* used in deblocking */
818        currMB->RefIdx[mbPartIdx] = video->RefPicList0[currMB->ref_idx_L0[mbPartIdx]]->RefIdx;
819    }
820    /* see subclause 7.4.5.1 for the range of ref_idx_lX */
821    max_ref_idx = sliceHdr->num_ref_idx_l1_active_minus1;
822    /*  if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
823            max_ref_idx = 2*sliceHdr->num_ref_idx_l1_active_minus1 + 1;*/
824
825    if (sliceHdr->num_ref_idx_l1_active_minus1 > 0)
826    {
827        for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
828        {
829            if (/*(sliceHdr->num_ref_idx_l1_active_minus1>0 || currMB->mb_field_decoding_flag) &&*/
830                /*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
831                currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
832            {
833                status = te_v(stream, currMB->ref_idx_L1[mbPartIdx], max_ref_idx);
834            }
835        }
836    }
837
838    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
839    {
840        if (/*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
841            currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
842        {
843            for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
844            {
845                status = se_v(stream, video->mvd_l0[mbPartIdx][subMbPartIdx][0]);
846                status = se_v(stream, video->mvd_l0[mbPartIdx][subMbPartIdx][1]);
847            }
848        }
849    }
850
851    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
852    {
853        if (/*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
854            currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
855        {
856            for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
857            {
858                status = se_v(stream, video->mvd_l1[mbPartIdx][subMbPartIdx][0]);
859                status = se_v(stream, video->mvd_l1[mbPartIdx][subMbPartIdx][1]);
860            }
861        }
862    }
863
864    return status;
865}
866
867/* input is mblock->sub_mb_type[] */
868void InterpretSubMBTypeP(AVCMacroblock *mblock, uint *sub_mb_type)
869{
870    int i;
871    /* see enum AVCMBType declaration */
872    /*const static AVCSubMBMode map2subMbMode[4] = {AVC_8x8,AVC_8x4,AVC_4x8,AVC_4x4};
873    const static int map2subPartWidth[4] = {8,8,4,4};
874    const static int map2subPartHeight[4] = {8,4,8,4};
875    const static int map2numSubPart[4] = {1,2,2,4};*/
876
877    for (i = 0; i < 4 ; i++)
878    {
879        sub_mb_type[i] = mblock->subMbMode[i] - AVC_8x8;
880    }
881
882    return ;
883}
884
885void InterpretSubMBTypeB(AVCMacroblock *mblock, uint *sub_mb_type)
886{
887    int i;
888    /* see enum AVCMBType declaration */
889    /*  const static AVCSubMBMode map2subMbMode[13] = {AVC_BDirect8,AVC_8x8,AVC_8x8,
890            AVC_8x8,AVC_8x4,AVC_4x8,AVC_8x4,AVC_4x8,AVC_8x4,AVC_4x8,AVC_4x4,AVC_4x4,AVC_4x4};
891        const static int map2subPartWidth[13] = {4,8,8,8,8,4,8,4,8,4,4,4,4};
892        const static int map2subPartHeight[13] = {4,8,8,8,4,8,4,8,4,8,4,4,4};
893        const static int map2numSubPart[13] = {4,1,1,1,2,2,2,2,2,2,4,4,4};
894        const static int map2predMode[13] = {3,0,1,2,0,0,1,1,2,2,0,1,2};*/
895
896    for (i = 0; i < 4 ; i++)
897    {
898        if (mblock->subMbMode[i] == AVC_BDirect8)
899        {
900            sub_mb_type[i] = 0;
901        }
902        else if (mblock->subMbMode[i] == AVC_8x8)
903        {
904            sub_mb_type[i] = 1 + mblock->MBPartPredMode[i][0];
905        }
906        else if (mblock->subMbMode[i] == AVC_4x4)
907        {
908            sub_mb_type[i] = 10 + mblock->MBPartPredMode[i][0];
909        }
910        else
911        {
912            sub_mb_type[i] = 4 + (mblock->MBPartPredMode[i][0] << 1) + (mblock->subMbMode[i] - AVC_8x4);
913        }
914    }
915
916    return ;
917}
918
919/* see subclause 8.3.1 */
920AVCEnc_Status EncodeIntra4x4Mode(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream)
921{
922    int intra4x4PredModeA = 0;
923    int intra4x4PredModeB, predIntra4x4PredMode;
924    int component, SubBlock_indx, block_x, block_y;
925    int dcOnlyPredictionFlag;
926    uint    flag;
927    int     rem = 0;
928    int     mode;
929    int bindx = 0;
930
931    for (component = 0; component < 4; component++) /* partition index */
932    {
933        block_x = ((component & 1) << 1);
934        block_y = ((component >> 1) << 1);
935
936        for (SubBlock_indx = 0; SubBlock_indx < 4; SubBlock_indx++) /* sub-partition index */
937        {
938            dcOnlyPredictionFlag = 0;
939            if (block_x > 0)
940            {
941                intra4x4PredModeA = currMB->i4Mode[(block_y << 2) + block_x - 1 ];
942            }
943            else
944            {
945                if (video->intraAvailA)
946                {
947                    if (video->mblock[video->mbAddrA].mbMode == AVC_I4)
948                    {
949                        intra4x4PredModeA = video->mblock[video->mbAddrA].i4Mode[(block_y << 2) + 3];
950                    }
951                    else
952                    {
953                        intra4x4PredModeA = AVC_I4_DC;
954                    }
955                }
956                else
957                {
958                    dcOnlyPredictionFlag = 1;
959                }
960            }
961
962            if (block_y > 0)
963            {
964                intra4x4PredModeB = currMB->i4Mode[((block_y-1) << 2) + block_x];
965            }
966            else
967            {
968                if (video->intraAvailB)
969                {
970                    if (video->mblock[video->mbAddrB].mbMode == AVC_I4)
971                    {
972                        intra4x4PredModeB = video->mblock[video->mbAddrB].i4Mode[(3 << 2) + block_x];
973                    }
974                    else
975                    {
976                        intra4x4PredModeB = AVC_I4_DC;
977                    }
978                }
979                else
980                {
981                    dcOnlyPredictionFlag = 1;
982                }
983            }
984
985            if (dcOnlyPredictionFlag)
986            {
987                intra4x4PredModeA = intra4x4PredModeB = AVC_I4_DC;
988            }
989
990            predIntra4x4PredMode = AVC_MIN(intra4x4PredModeA, intra4x4PredModeB);
991
992            flag = 0;
993            mode = currMB->i4Mode[(block_y<<2)+block_x];
994
995            if (mode == (AVCIntra4x4PredMode)predIntra4x4PredMode)
996            {
997                flag = 1;
998            }
999            else if (mode < predIntra4x4PredMode)
1000            {
1001                rem = mode;
1002            }
1003            else
1004            {
1005                rem = mode - 1;
1006            }
1007
1008            BitstreamWrite1Bit(stream, flag);
1009
1010            if (!flag)
1011            {
1012                BitstreamWriteBits(stream, 3, rem);
1013            }
1014
1015            bindx++;
1016            block_y += (SubBlock_indx & 1) ;
1017            block_x += (1 - 2 * (SubBlock_indx & 1)) ;
1018        }
1019    }
1020
1021    return AVCENC_SUCCESS;
1022}
1023
1024
1025
1026