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 
AVCEncodeSlice(AVCEncObject * encvid)21 AVCEnc_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 
EncodeMB(AVCEncObject * encvid)153 AVCEnc_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 */
Copy_MB(uint8 * curL,uint8 * curCb,uint8 * curCr,uint8 * predBlock,int picPitch)511 void 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 */
EncodeMBHeader(AVCMacroblock * currMB,AVCEncObject * encvid)550 AVCEnc_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 */
InterpretMBType(AVCMacroblock * currMB,int slice_type)602 uint 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 */
mb_pred(AVCCommonObj * video,AVCMacroblock * currMB,AVCEncBitstream * stream)686 AVCEnc_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 */
sub_mb_pred(AVCCommonObj * video,AVCMacroblock * currMB,AVCEncBitstream * stream)772 AVCEnc_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[] */
InterpretSubMBTypeP(AVCMacroblock * mblock,uint * sub_mb_type)868 void 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 
InterpretSubMBTypeB(AVCMacroblock * mblock,uint * sub_mb_type)885 void 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 */
EncodeIntra4x4Mode(AVCCommonObj * video,AVCMacroblock * currMB,AVCEncBitstream * stream)920 AVCEnc_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