1 /*
2 * Copyright(c) 2018 Intel Corporation
3 * SPDX - License - Identifier: BSD - 2 - Clause - Patent
4 */
5 
6 /***************************************
7 * Includes
8 ***************************************/
9 #include <stdlib.h>
10 
11 #include "EbDefinitions.h"
12 #include "EbUtility.h"
13 #include "EbSequenceControlSet.h"
14 
15 #include "EbModeDecision.h"
16 #include "EbAdaptiveMotionVectorPrediction.h"
17 #include "EbMvMerge.h"
18 #include "EbTransformUnit.h"
19 #include "EbModeDecisionProcess.h"
20 #include "EbComputeSAD.h"
21 #include "EbModeDecisionConfiguration.h"
22 
23 /********************************************
24 * Constants
25 ********************************************/
26 static EB_U32  AntiContouringIntraMode[11] = { EB_INTRA_PLANAR, EB_INTRA_DC, EB_INTRA_HORIZONTAL, EB_INTRA_VERTICAL,
27 EB_INTRA_MODE_2, EB_INTRA_MODE_6, EB_INTRA_MODE_14, EB_INTRA_MODE_18, EB_INTRA_MODE_22, EB_INTRA_MODE_30, EB_INTRA_MODE_34 };
28 
29 EB_BOOL AntiContouringIntraModeValidityPerDepth[35] =
30 {
31 	EB_TRUE, EB_TRUE,
32     EB_TRUE, EB_FALSE, EB_FALSE, EB_FALSE,
33     EB_TRUE, EB_FALSE, EB_FALSE, EB_FALSE,
34     EB_TRUE, EB_FALSE, EB_FALSE, EB_FALSE,
35     EB_TRUE, EB_FALSE, EB_FALSE, EB_FALSE,
36     EB_TRUE, EB_FALSE, EB_FALSE, EB_FALSE,
37 	EB_TRUE, EB_FALSE, EB_FALSE, EB_FALSE,
38     EB_TRUE, EB_FALSE, EB_FALSE, EB_FALSE,
39     EB_TRUE, EB_FALSE, EB_FALSE, EB_FALSE,
40     EB_TRUE
41 
42 };
43 
44 
45 const EB_U32 EbHevcParentIndex[85] = { 0, 0, 0, 2, 2, 2, 2, 0, 7, 7, 7, 7, 0, 12, 12, 12, 12, 0, 17, 17, 17, 17, 0, 0,
46 23, 23, 23, 23, 0, 28, 28, 28, 28, 0, 33, 33, 33, 33, 0, 38, 38, 38, 38, 0, 0,
47 44, 44, 44, 44, 0, 49, 49, 49, 49, 0, 54, 54, 54, 54, 0, 59, 59, 59, 59, 0, 0,
48 65, 65, 65, 65, 0, 70, 70, 70, 70, 0, 75, 75, 75, 75, 0, 80, 80, 80, 80 };
49 
50 static EB_BOOL CheckForMvOverBound(
51     EB_S16 mvx,
52     EB_S16 mvy,
53     ModeDecisionContext_t           *ctxtPtr,
54     const LargestCodingUnit_t *lcuPtr);
55 
56 EB_ERRORTYPE IntraPredOnSrc(
57     ModeDecisionContext_t                  *mdContextPtr,
58     EB_U32                                  componentMask,
59     PictureControlSet_t                    *pictureControlSetPtr,
60     EbPictureBufferDesc_t                  * predictionPtr,
61     EB_U32                                   intraMode);
62 
63 
64 EB_U8 GetNumOfIntraModesFromOisPoint(
65     PictureParentControlSet_t   *pictureControlSetPtr,
66     EB_U32                       meSad,
67     EB_U32                       oisDcSad
68 );
69 extern EB_U32 stage1ModesArray[];
70 
intraSearchTheseModesOutputBest(ModeDecisionContext_t * contextPtr,PictureControlSet_t * pictureControlSetPtr,EB_U8 * src,EB_U32 srcStride,EB_U8 NumOfModesToTest,EB_U32 * bestMode,EB_U32 * bestSADOut)71 void intraSearchTheseModesOutputBest(
72     ModeDecisionContext_t                *contextPtr,
73     PictureControlSet_t                 *pictureControlSetPtr,
74     EB_U8                                *src,
75     EB_U32                               srcStride,
76     EB_U8                                NumOfModesToTest,
77     EB_U32                              *bestMode,
78     EB_U32                              *bestSADOut
79 )
80 {
81     EB_U32   cuSize = contextPtr->cuSize;
82     EB_U32   candidateIndex;
83     EB_U32   mode;
84     EB_U32   bestSAD = 32 * 32 * 255;
85     EB_U32	 sadCurr;
86 
87 
88     for (candidateIndex = 0; candidateIndex < NumOfModesToTest; candidateIndex++) {
89 
90         mode =  stage1ModesArray[candidateIndex];
91 
92         // Intra Prediction
93         IntraPredOnSrc(
94             contextPtr,
95             PICTURE_BUFFER_DESC_LUMA_MASK,
96             pictureControlSetPtr,
97             contextPtr->predictionBuffer,
98             mode);
99 
100         const EB_U32 puOriginIndex = (contextPtr->cuOriginY & 63) * 64 + (contextPtr->cuOriginX & 63);
101 
102         //Distortion
103         sadCurr  = (EB_U32)NxMSadKernel_funcPtrArray[!!(ASM_TYPES & AVX2_MASK)][cuSize >> 3](
104             src,
105             srcStride,
106             &(contextPtr->predictionBuffer->bufferY[puOriginIndex]),
107             MAX_LCU_SIZE,
108             cuSize,
109             cuSize);
110 
111         //keep track of best SAD
112         if (sadCurr < bestSAD) {
113             *bestMode = mode;
114             bestSAD = sadCurr;
115         }
116 
117     }
118     *bestSADOut = bestSAD;
119 }
120 
ModeDecisionCandidateBufferDctor(EB_PTR p)121 static void ModeDecisionCandidateBufferDctor(EB_PTR p)
122 {
123     ModeDecisionCandidateBuffer_t *obj = (ModeDecisionCandidateBuffer_t*)p;
124     EB_DELETE(obj->predictionPtr);
125     EB_DELETE(obj->residualQuantCoeffPtr);
126     EB_DELETE(obj->reconCoeffPtr);
127     EB_DELETE(obj->reconPtr);
128 }
129 
130 /***************************************
131 * Mode Decision Candidate Ctor
132 ***************************************/
ModeDecisionCandidateBufferCtor(ModeDecisionCandidateBuffer_t * bufferPtr,EB_U16 lcuMaxSize,EB_BITDEPTH maxBitdepth,EB_U64 * fastCostPtr,EB_U64 * fullCostPtr,EB_U64 * fullCostSkipPtr,EB_U64 * fullCostMergePtr)133 EB_ERRORTYPE ModeDecisionCandidateBufferCtor(
134     ModeDecisionCandidateBuffer_t  *bufferPtr,
135     EB_U16                          lcuMaxSize,
136     EB_BITDEPTH                     maxBitdepth,
137     EB_U64                         *fastCostPtr,
138     EB_U64                         *fullCostPtr,
139     EB_U64                         *fullCostSkipPtr,
140     EB_U64                         *fullCostMergePtr)
141 {
142     EbPictureBufferDescInitData_t pictureBufferDescInitData;
143     EbPictureBufferDescInitData_t doubleWidthPictureBufferDescInitData;
144     bufferPtr->dctor = ModeDecisionCandidateBufferDctor;
145 
146     // Init Picture Data
147     pictureBufferDescInitData.maxWidth = lcuMaxSize;
148     pictureBufferDescInitData.maxHeight = lcuMaxSize;
149     pictureBufferDescInitData.bitDepth = maxBitdepth;
150     pictureBufferDescInitData.bufferEnableMask = PICTURE_BUFFER_DESC_FULL_MASK;
151     pictureBufferDescInitData.colorFormat = EB_YUV420;
152     pictureBufferDescInitData.leftPadding = 0;
153     pictureBufferDescInitData.rightPadding = 0;
154     pictureBufferDescInitData.topPadding = 0;
155     pictureBufferDescInitData.botPadding = 0;
156     pictureBufferDescInitData.splitMode = EB_FALSE;
157 
158     doubleWidthPictureBufferDescInitData.maxWidth = lcuMaxSize;
159     doubleWidthPictureBufferDescInitData.maxHeight = lcuMaxSize;
160     doubleWidthPictureBufferDescInitData.bitDepth = EB_16BIT;
161     doubleWidthPictureBufferDescInitData.bufferEnableMask = PICTURE_BUFFER_DESC_FULL_MASK;
162     doubleWidthPictureBufferDescInitData.colorFormat = EB_YUV420;
163     doubleWidthPictureBufferDescInitData.leftPadding = 0;
164     doubleWidthPictureBufferDescInitData.rightPadding = 0;
165     doubleWidthPictureBufferDescInitData.topPadding = 0;
166     doubleWidthPictureBufferDescInitData.botPadding = 0;
167     doubleWidthPictureBufferDescInitData.splitMode = EB_FALSE;
168 
169     // Video Buffers
170     EB_NEW(
171         bufferPtr->predictionPtr,
172         EbPictureBufferDescCtor,
173         (EB_PTR)&pictureBufferDescInitData);
174 
175     EB_NEW(
176         bufferPtr->residualQuantCoeffPtr,
177         EbPictureBufferDescCtor,
178         (EB_PTR)&doubleWidthPictureBufferDescInitData);
179 
180     EB_NEW(
181         bufferPtr->reconCoeffPtr,
182         EbPictureBufferDescCtor,
183         (EB_PTR)&doubleWidthPictureBufferDescInitData);
184 
185     EB_NEW(
186         bufferPtr->reconPtr,
187         EbPictureBufferDescCtor,
188         (EB_PTR)&pictureBufferDescInitData);
189 
190     // Costs
191     bufferPtr->fastCostPtr = fastCostPtr;
192     bufferPtr->fullCostPtr = fullCostPtr;
193     bufferPtr->fullCostSkipPtr = fullCostSkipPtr;
194     bufferPtr->fullCostMergePtr = fullCostMergePtr;
195     return EB_ErrorNone;
196 }
197 
198 
199 // Function Declarations
RoundMv(ModeDecisionCandidate_t * candidateArray,EB_U32 canTotalCnt)200 void RoundMv(
201     ModeDecisionCandidate_t	*candidateArray,
202     EB_U32                   canTotalCnt)
203 {
204 
205     candidateArray[canTotalCnt].motionVector_x_L0 = (candidateArray[canTotalCnt].motionVector_x_L0 + 2)&~0x03;
206     candidateArray[canTotalCnt].motionVector_y_L0 = (candidateArray[canTotalCnt].motionVector_y_L0 + 2)&~0x03;
207 
208     candidateArray[canTotalCnt].motionVector_x_L1 = (candidateArray[canTotalCnt].motionVector_x_L1 + 2)&~0x03;
209     candidateArray[canTotalCnt].motionVector_y_L1 = (candidateArray[canTotalCnt].motionVector_y_L1 + 2)&~0x03;
210 
211     return;
212 
213 }
214 
SetMvpClipMVs(ModeDecisionCandidate_t * candidatePtr,EB_U32 cuOriginX,EB_U32 cuOriginY,EB_U32 puIndex,EB_U32 tbSize,PictureControlSet_t * pictureControlSetPtr)215 EB_ERRORTYPE SetMvpClipMVs(
216     ModeDecisionCandidate_t  *candidatePtr,
217     EB_U32                    cuOriginX,
218     EB_U32                    cuOriginY,
219     EB_U32                    puIndex,
220     EB_U32                    tbSize,
221     PictureControlSet_t      *pictureControlSetPtr)
222 {
223     EB_ERRORTYPE  return_error = EB_ErrorNone;
224 
225     EB_U32        pictureWidth = ((SequenceControlSet_t*)pictureControlSetPtr->sequenceControlSetWrapperPtr->objectPtr)->lumaWidth;
226     EB_U32        pictureHeight = ((SequenceControlSet_t*)pictureControlSetPtr->sequenceControlSetWrapperPtr->objectPtr)->lumaHeight;
227 
228     candidatePtr->motionVectorPredIdx[REF_LIST_0] = 0;
229     candidatePtr->motionVectorPred_x[REF_LIST_0]  = 0;
230     candidatePtr->motionVectorPred_y[REF_LIST_0]  = 0;
231     candidatePtr->motionVectorPredIdx[REF_LIST_1] = 0;
232     candidatePtr->motionVectorPred_x[REF_LIST_1]  = 0;
233     candidatePtr->motionVectorPred_y[REF_LIST_1]  = 0;
234 
235     switch(candidatePtr->predictionDirection[puIndex]) {
236     case UNI_PRED_LIST_0:
237         // Clip the input MV
238         ClipMV(
239             cuOriginX,
240             cuOriginY,
241             &candidatePtr->motionVector_x_L0,
242             &candidatePtr->motionVector_y_L0,
243             pictureWidth,
244             pictureHeight,
245             tbSize);
246 
247         break;
248 
249     case UNI_PRED_LIST_1:
250 
251         // Clip the input MV
252        ClipMV(
253             cuOriginX,
254             cuOriginY,
255             &candidatePtr->motionVector_x_L1,
256             &candidatePtr->motionVector_y_L1,
257             pictureWidth,
258             pictureHeight,
259             tbSize);
260 
261         break;
262 
263     case BI_PRED:
264 
265         // Choose the MVP in list0
266         // Clip the input MV
267         ClipMV(
268             cuOriginX,
269             cuOriginY,
270             &candidatePtr->motionVector_x_L0,
271             &candidatePtr->motionVector_y_L0,
272             pictureWidth,
273             pictureHeight,
274             tbSize);
275 
276         // Choose the MVP in list1
277         // Clip the input MV
278         ClipMV(
279             cuOriginX,
280             cuOriginY,
281             &candidatePtr->motionVector_x_L1,
282             &candidatePtr->motionVector_y_L1,
283             pictureWidth,
284             pictureHeight,
285             tbSize);
286         break;
287 
288     default:
289         break;
290     }
291 
292     return return_error;
293 }
294 
295 /***************************************
296 * Pre-Mode Decision
297 *   Selects which fast cost modes to
298 *   do full reconstruction on.
299 ***************************************/
PreModeDecision(CodingUnit_t * cuPtr,EB_U32 bufferTotalCount,ModeDecisionCandidateBuffer_t ** bufferPtrArray,EB_U32 * fullCandidateTotalCountPtr,EB_U8 * bestCandidateIndexArray,EB_U8 * disableMergeIndex,EB_BOOL sameFastFullCandidate)300 EB_ERRORTYPE PreModeDecision(
301 	CodingUnit_t                   *cuPtr,
302 	EB_U32                          bufferTotalCount,
303 	ModeDecisionCandidateBuffer_t **bufferPtrArray,
304 	EB_U32                         *fullCandidateTotalCountPtr,
305 	EB_U8                          *bestCandidateIndexArray,
306 	EB_U8                          *disableMergeIndex,
307     EB_BOOL                         sameFastFullCandidate
308     )
309 {
310 	EB_ERRORTYPE return_error = EB_ErrorNone;
311 	EB_U32 fullCandidateIndex;
312 	EB_U32 fullReconCandidateCount;
313 	EB_U32                          highestCostIndex;
314 	EB_U64                          highestCost;
315 	EB_U32                          candIndx = 0, i, j, index;
316 
317 	*fullCandidateTotalCountPtr = bufferTotalCount;
318 
319 	//Second,  We substract one, because with N buffers we can determine the best N-1 candidates.
320 	//Note/TODO: in the case number of fast candidate is less or equal to the number of buffers, N buffers would be enough
321     if (sameFastFullCandidate){
322         fullReconCandidateCount = MAX(1, (*fullCandidateTotalCountPtr));
323     }
324     else{
325         fullReconCandidateCount = MAX(1, (*fullCandidateTotalCountPtr) - 1);
326     }
327 
328 	//With N buffers, we get here with the best N-1, plus the last candidate. We need to exclude the worst, and keep the best N-1.
329 	highestCost = *(bufferPtrArray[0]->fastCostPtr);
330 	highestCostIndex = 0;
331 
332 	if (bufferTotalCount > 1){
333         if (sameFastFullCandidate){
334             for (i = 0; i < bufferTotalCount; i++) {
335                 bestCandidateIndexArray[candIndx++] = (EB_U8)i;
336             }
337         }
338         else{
339             for (i = 1; i < bufferTotalCount; i++) {
340 
341                 if (*(bufferPtrArray[i]->fastCostPtr) >= highestCost){
342                     highestCost = *(bufferPtrArray[i]->fastCostPtr);
343                     highestCostIndex = i;
344                 }
345             }
346             for (i = 0; i < bufferTotalCount; i++) {
347 
348                 if (i != highestCostIndex){
349                     bestCandidateIndexArray[candIndx++] = (EB_U8)i;
350                 }
351             }
352         }
353 
354 	}
355 	else
356 		bestCandidateIndexArray[0] = 0;
357 	for(i = 0; i < fullReconCandidateCount - 1; ++i) {
358 		for (j = i + 1; j < fullReconCandidateCount; ++j) {
359 			if ((bufferPtrArray[bestCandidateIndexArray[i]]->candidatePtr->type == INTRA_MODE) &&
360 				(bufferPtrArray[bestCandidateIndexArray[j]]->candidatePtr->type == INTER_MODE)){
361 				index = bestCandidateIndexArray[i];
362 				bestCandidateIndexArray[i] = (EB_U8)bestCandidateIndexArray[j];
363 				bestCandidateIndexArray[j] = (EB_U8)index;
364 			}
365 		}
366 	}
367 
368 	// Set (*fullCandidateTotalCountPtr) to fullReconCandidateCount
369 	(*fullCandidateTotalCountPtr) = fullReconCandidateCount;
370 
371 	for (i = 0; i < fullReconCandidateCount; ++i) {
372 		fullCandidateIndex = bestCandidateIndexArray[i];
373 
374 		// Next, Set the transformSize
375 		bufferPtrArray[fullCandidateIndex]->candidatePtr->transformSize       = (EB_U8)(CLIP3(TRANSFORM_MIN_SIZE, TRANSFORM_MAX_SIZE, GetCodedUnitStats(cuPtr->leafIndex)->size));
376 		bufferPtrArray[fullCandidateIndex]->candidatePtr->transformChromaSize = (EB_U8)(CLIP3(TRANSFORM_MIN_SIZE, TRANSFORM_MAX_SIZE, bufferPtrArray[fullCandidateIndex]->candidatePtr->transformSize >> 1));
377 
378         // Set disableMergeIndex
379 		*disableMergeIndex = bufferPtrArray[fullCandidateIndex]->candidatePtr->type == INTER_MODE ? 1 : *disableMergeIndex;
380 	}
381 
382 	return return_error;
383 }
384 
LimitMvOverBound(EB_S16 * mvx,EB_S16 * mvy,ModeDecisionContext_t * ctxtPtr,const LargestCodingUnit_t * lcuPtr)385 static void LimitMvOverBound(
386     EB_S16 *mvx,
387     EB_S16 *mvy,
388     ModeDecisionContext_t           *ctxtPtr,
389     const LargestCodingUnit_t *lcuPtr)
390 {
391     EB_S32 mvxF, mvyF;
392 
393     //L0
394     mvxF = *mvx;
395     mvyF = *mvy;
396 
397     EB_S32 cuOriginX = (EB_S32)ctxtPtr->cuOriginX << 2;
398     EB_S32 cuOriginY = (EB_S32)ctxtPtr->cuOriginY << 2;
399 
400     EB_S32 startX = lcuPtr->tileInfoPtr->tilePxlOriginX << 2;
401     EB_S32 startY = lcuPtr->tileInfoPtr->tilePxlOriginY << 2;
402     EB_S32 endX   = lcuPtr->tileInfoPtr->tilePxlEndX << 2;
403     EB_S32 endY   = lcuPtr->tileInfoPtr->tilePxlEndY << 2;
404     EB_S32 cuSize = (EB_S32)ctxtPtr->cuStats->size << 2;
405     EB_S32 pad = (4 << 2);
406     EB_S32 mvxFL = mvxF;
407     EB_S32 mvxFR = mvxF;
408     EB_S32 mvyFT = mvyF;
409     EB_S32 mvyFB = mvyF;
410 
411     //if MV is quarter/half, the 7,8 tap interpolation will cross the boundary
412     //calculate delta for luma/chroma MVs to be integer values
413     // Horizontal
414     if (((mvxF % 16) != 0) &&
415             (cuOriginX + mvxF + cuSize > (endX - pad) || (cuOriginX + mvxF < (startX + pad)))) {
416         //half/quarter interpolation, and cross the boundary, clamp to integer first
417         mvxFL = ((mvxF >> 4) << 4);
418         mvxFR = (((mvxF+15) >> 4) << 4);
419     }
420 
421     if (cuOriginX + mvxFR + cuSize >= endX) {
422         *mvx = endX - cuSize - cuOriginX;
423     }
424 
425     if (cuOriginX + mvxFL <= startX) {
426         *mvx = startX - cuOriginX;
427     }
428 
429     // Vertical
430     if (((mvyF % 16) != 0) &&
431             (cuOriginY + mvyF + cuSize > (endY - pad) || (cuOriginY + mvyF < (startY + pad)))) {
432         //half/quarter interpolation, and cross the boundary, clamp to integer first
433         mvyFT = ((mvyF >> 4) << 4);
434         mvyFB = (((mvyF+15) >> 4) << 4);
435     }
436 
437     if (cuOriginY + mvyFB + cuSize >= endY) {
438         *mvy = endY - cuSize - cuOriginY;
439     }
440 
441     if (cuOriginY + mvyFT <= startY) {
442         *mvy = startY - cuOriginY;
443     }
444 }
445 
Me2Nx2NCandidatesInjection(PictureControlSet_t * pictureControlSetPtr,ModeDecisionContext_t * contextPtr,const SequenceControlSet_t * sequenceControlSetPtr,LargestCodingUnit_t * lcuPtr,const EB_U32 me2Nx2NTableOffset,EB_U32 * candidateTotalCnt,EB_S16 firstPuAMVPCandArray_x[MAX_NUM_OF_REF_PIC_LIST][2],EB_S16 firstPuAMVPCandArray_y[MAX_NUM_OF_REF_PIC_LIST][2],EB_U32 firstPuNumAvailableAMVPCand[MAX_NUM_OF_REF_PIC_LIST])446 void Me2Nx2NCandidatesInjection(
447     PictureControlSet_t            *pictureControlSetPtr,
448     ModeDecisionContext_t          *contextPtr,
449     const SequenceControlSet_t     *sequenceControlSetPtr,
450     LargestCodingUnit_t            *lcuPtr,
451     const EB_U32                    me2Nx2NTableOffset,
452     EB_U32                         *candidateTotalCnt,
453     EB_S16                          firstPuAMVPCandArray_x[MAX_NUM_OF_REF_PIC_LIST][2],
454     EB_S16                          firstPuAMVPCandArray_y[MAX_NUM_OF_REF_PIC_LIST][2],
455     EB_U32                          firstPuNumAvailableAMVPCand[MAX_NUM_OF_REF_PIC_LIST]
456     )
457 {
458     EB_U32                   meCandidateIndex;
459     EB_U32                   canTotalCnt           = (*candidateTotalCnt);
460     const EB_U32             lcuAddr               = lcuPtr->index;
461     const EB_U32             cuOriginX             = contextPtr->cuOriginX;
462 	const EB_U32             cuOriginY             = contextPtr->cuOriginY;
463 
464 	MeCuResults_t * mePuResult = &pictureControlSetPtr->ParentPcsPtr->meResults[lcuAddr][me2Nx2NTableOffset];
465 	ModeDecisionCandidate_t	*candidateArray = contextPtr->fastCandidateArray;
466 	const EB_U32             meTotalCnt = mePuResult->totalMeCandidateIndex;
467 
468 	for (meCandidateIndex = 0; meCandidateIndex < meTotalCnt; ++meCandidateIndex)
469 	{
470 
471 
472 
473 		const EB_U32 interDirection = mePuResult->distortionDirection[meCandidateIndex].direction;
474         if (interDirection == BI_PRED &&  pictureControlSetPtr->ParentPcsPtr->depthMode == PICT_LCU_SWITCH_DEPTH_MODE && pictureControlSetPtr->ParentPcsPtr->lcuMdModeArray[lcuPtr->index] == LCU_PRED_OPEN_LOOP_1_NFL_DEPTH_MODE)
475             continue;
476         candidateArray[canTotalCnt].motionVector_x_L0 = mePuResult->xMvL0;
477         candidateArray[canTotalCnt].motionVector_y_L0 = mePuResult->yMvL0;
478         candidateArray[canTotalCnt].motionVector_x_L1 = mePuResult->xMvL1;
479         candidateArray[canTotalCnt].motionVector_y_L1 = mePuResult->yMvL1;
480 
481         if (pictureControlSetPtr->ParentPcsPtr->useSubpelFlag == 0){
482             RoundMv(candidateArray,
483                 canTotalCnt);
484         }
485 
486         //constrain mv
487         if (sequenceControlSetPtr->staticConfig.unrestrictedMotionVector == 0) {
488             if (interDirection == UNI_PRED_LIST_0) {
489                 LimitMvOverBound(
490                     &candidateArray[canTotalCnt].motionVector_x_L0,
491                     &candidateArray[canTotalCnt].motionVector_y_L0,
492                     contextPtr,
493                     lcuPtr);
494             }
495             else if (interDirection == UNI_PRED_LIST_1) {
496                 LimitMvOverBound(
497                     &candidateArray[canTotalCnt].motionVector_x_L1,
498                     &candidateArray[canTotalCnt].motionVector_y_L1,
499                     contextPtr,
500                     lcuPtr);
501             }
502             else {
503                 LimitMvOverBound(
504                     &candidateArray[canTotalCnt].motionVector_x_L0,
505                     &candidateArray[canTotalCnt].motionVector_y_L0,
506                     contextPtr,
507                     lcuPtr);
508 
509                 LimitMvOverBound(
510                     &candidateArray[canTotalCnt].motionVector_x_L1,
511                     &candidateArray[canTotalCnt].motionVector_y_L1,
512                     contextPtr,
513                     lcuPtr);
514             }
515         }
516 
517 		candidateArray[canTotalCnt].meDistortion = mePuResult->distortionDirection[meCandidateIndex].distortion;
518 
519         candidateArray[canTotalCnt].distortionReady         = 1;
520 
521         candidateArray[canTotalCnt].predictionDirection[0] = (EB_PREDDIRECTION)interDirection;
522 
523         candidateArray[canTotalCnt].type                   = INTER_MODE;
524         candidateArray[canTotalCnt].mergeFlag              = EB_FALSE;
525         if (contextPtr->generateAmvpTableMd == EB_FALSE)
526         {
527             // TODO: Clips mvs along with Limit mvs
528             SetMvpClipMVs(
529                 &candidateArray[canTotalCnt],
530                 cuOriginX,
531                 cuOriginY,
532                 0,
533                 sequenceControlSetPtr->lcuSize,
534                 pictureControlSetPtr
535             );
536 
537         }
538         else
539         {
540 
541             ChooseMVPIdx_V2(
542                 &candidateArray[canTotalCnt],
543                 cuOriginX,
544                 cuOriginY,
545                 0,
546                 sequenceControlSetPtr->lcuSize,
547                 firstPuAMVPCandArray_x[REF_LIST_0],
548                 firstPuAMVPCandArray_y[REF_LIST_0],
549                 firstPuNumAvailableAMVPCand[REF_LIST_0],
550                 firstPuAMVPCandArray_x[REF_LIST_1],
551                 firstPuAMVPCandArray_y[REF_LIST_1],
552                 firstPuNumAvailableAMVPCand[REF_LIST_1],
553                 pictureControlSetPtr);
554 
555         }
556 
557 
558         canTotalCnt++;
559     }
560 
561     // update the total number of candidates injected
562     (*candidateTotalCnt) = canTotalCnt;
563 
564 
565  return;
566 }
567 
Amvp2Nx2NCandidatesInjection(PictureControlSet_t * pictureControlSetPtr,ModeDecisionContext_t * contextPtr,const SequenceControlSet_t * sequenceControlSetPtr,EB_U32 * candidateTotalCnt,EB_S16 firstPuAMVPCandArray_x[MAX_NUM_OF_REF_PIC_LIST][2],EB_S16 firstPuAMVPCandArray_y[MAX_NUM_OF_REF_PIC_LIST][2],EB_U32 firstPuNumAvailableAMVPCand[MAX_NUM_OF_REF_PIC_LIST])568 void Amvp2Nx2NCandidatesInjection(
569     PictureControlSet_t            *pictureControlSetPtr,
570     ModeDecisionContext_t          *contextPtr,
571     const SequenceControlSet_t     *sequenceControlSetPtr,
572     EB_U32                         *candidateTotalCnt,
573     EB_S16                          firstPuAMVPCandArray_x[MAX_NUM_OF_REF_PIC_LIST][2],
574     EB_S16                          firstPuAMVPCandArray_y[MAX_NUM_OF_REF_PIC_LIST][2],
575     EB_U32                          firstPuNumAvailableAMVPCand[MAX_NUM_OF_REF_PIC_LIST]
576 )
577 {
578     ModeDecisionCandidate_t	*candidateArray = contextPtr->fastCandidateArray;
579 
580 
581 
582     EB_PREDDIRECTION interDirection;
583     EB_U8            amvpCandidateIndex;
584     EB_BOOL          isAmvpCandidateAvailable;
585 
586     const EB_U32     cuOriginX = contextPtr->cuOriginX;
587     const EB_U32     cuOriginY = contextPtr->cuOriginY;
588     EB_U32                   canTotalCnt = (*candidateTotalCnt);
589 
590     for (interDirection = UNI_PRED_LIST_0; interDirection <= (pictureControlSetPtr->sliceType == EB_B_PICTURE ? BI_PRED : UNI_PRED_LIST_0); ++interDirection)
591     {
592 
593         const unsigned targetRefList = (interDirection == UNI_PRED_LIST_0 || interDirection == BI_PRED) ? REF_LIST_0 : REF_LIST_1;
594 
595         amvpCandidateIndex = 0;
596 
597         for (amvpCandidateIndex = 0; amvpCandidateIndex < MAX_AMVP_CANDIDATES_PER_REF_LIST; amvpCandidateIndex++)
598         {
599             EB_BOOL mvOutOfPicFlag = EB_FALSE;
600             isAmvpCandidateAvailable = EB_TRUE;
601 
602             switch (amvpCandidateIndex)
603             {
604             case ZERO:
605 
606                 candidateArray[canTotalCnt].motionVector_x_L0 = 0;
607                 candidateArray[canTotalCnt].motionVector_y_L0 = 0;
608 
609                 candidateArray[canTotalCnt].motionVector_x_L1 = 0;
610                 candidateArray[canTotalCnt].motionVector_y_L1 = 0;
611 
612                 break;
613 
614             case AMVP0:
615                 candidateArray[canTotalCnt].motionVector_x_L0 = firstPuAMVPCandArray_x[REF_LIST_0][0];
616                 candidateArray[canTotalCnt].motionVector_y_L0 = firstPuAMVPCandArray_y[REF_LIST_0][0];
617 
618                 candidateArray[canTotalCnt].motionVector_x_L1 = firstPuAMVPCandArray_x[REF_LIST_1][0];
619                 candidateArray[canTotalCnt].motionVector_y_L1 = firstPuAMVPCandArray_y[REF_LIST_1][0];
620 
621                 break;
622 
623             case AMVP1:
624 
625                 if (interDirection == BI_PRED) {
626                     if (firstPuNumAvailableAMVPCand[REF_LIST_0] == 2 && firstPuNumAvailableAMVPCand[REF_LIST_1] == 2) {
627 
628                         candidateArray[canTotalCnt].motionVector_x_L0 = firstPuAMVPCandArray_x[REF_LIST_0][1];
629                         candidateArray[canTotalCnt].motionVector_y_L0 = firstPuAMVPCandArray_y[REF_LIST_0][1];
630 
631                         candidateArray[canTotalCnt].motionVector_x_L1 = firstPuAMVPCandArray_x[REF_LIST_1][1];
632                         candidateArray[canTotalCnt].motionVector_y_L1 = firstPuAMVPCandArray_y[REF_LIST_1][1];
633 
634                     }
635                     else {
636                         isAmvpCandidateAvailable = EB_FALSE;
637                     }
638                 }
639                 else {
640                     if (firstPuNumAvailableAMVPCand[targetRefList] == 2) {
641                         if (targetRefList == REF_LIST_0) {
642                             candidateArray[canTotalCnt].motionVector_x_L0 = firstPuAMVPCandArray_x[targetRefList][1];
643                             candidateArray[canTotalCnt].motionVector_y_L0 = firstPuAMVPCandArray_y[targetRefList][1];
644                         }
645                         else {
646                             candidateArray[canTotalCnt].motionVector_x_L1 = firstPuAMVPCandArray_x[targetRefList][1];
647                             candidateArray[canTotalCnt].motionVector_y_L1 = firstPuAMVPCandArray_y[targetRefList][1];
648                         }
649                     }
650                     else {
651                         isAmvpCandidateAvailable = EB_FALSE;
652                     }
653                 }
654 
655                 break;
656             }
657 
658             if (sequenceControlSetPtr->staticConfig.unrestrictedMotionVector == 0) {
659                 if (interDirection == UNI_PRED_LIST_0) {
660                     mvOutOfPicFlag = CheckForMvOverBound(
661                                 candidateArray[canTotalCnt].motionVector_x_L0,
662                                 candidateArray[canTotalCnt].motionVector_y_L0,
663                                 contextPtr,
664                                 contextPtr->lcuPtr);
665                 }
666                 else if (interDirection == UNI_PRED_LIST_1) {
667                     mvOutOfPicFlag = CheckForMvOverBound(
668                                 candidateArray[canTotalCnt].motionVector_x_L1,
669                                 candidateArray[canTotalCnt].motionVector_y_L1,
670                                 contextPtr,
671                                 contextPtr->lcuPtr);
672                 }
673                 else {
674                     mvOutOfPicFlag = CheckForMvOverBound(
675                                 candidateArray[canTotalCnt].motionVector_x_L0,
676                                 candidateArray[canTotalCnt].motionVector_y_L0,
677                                 contextPtr,
678                                 contextPtr->lcuPtr);
679                     mvOutOfPicFlag |= CheckForMvOverBound(
680                                 candidateArray[canTotalCnt].motionVector_x_L1,
681                                 candidateArray[canTotalCnt].motionVector_y_L1,
682                                 contextPtr,
683                                 contextPtr->lcuPtr);
684                 }
685             }
686 
687             if (isAmvpCandidateAvailable && mvOutOfPicFlag == EB_FALSE) {
688                 candidateArray[canTotalCnt].distortionReady = 0;
689 
690                 candidateArray[canTotalCnt].predictionDirection[0] = (EB_PREDDIRECTION)interDirection;
691 
692                 candidateArray[canTotalCnt].type = INTER_MODE;
693                 candidateArray[canTotalCnt].mergeFlag = EB_FALSE;
694 
695                 if (pictureControlSetPtr->ParentPcsPtr->useSubpelFlag == 0) {
696                     RoundMv(candidateArray,
697                         canTotalCnt);
698                 }
699 
700 
701                 if (contextPtr->generateAmvpTableMd == EB_FALSE)
702                 {
703                     // TODO: Clips mvs along with Limit mvs
704                     SetMvpClipMVs(
705                         &candidateArray[canTotalCnt],
706                         cuOriginX,
707                         cuOriginY,
708                         0,
709                         sequenceControlSetPtr->lcuSize,
710                         pictureControlSetPtr
711                     );
712 
713                 }
714                 else
715                 {
716 
717                     ChooseMVPIdx_V2(
718                         &candidateArray[canTotalCnt],
719                         cuOriginX,
720                         cuOriginY,
721                         0,
722                         sequenceControlSetPtr->lcuSize,
723                         firstPuAMVPCandArray_x[REF_LIST_0],
724                         firstPuAMVPCandArray_y[REF_LIST_0],
725                         firstPuNumAvailableAMVPCand[REF_LIST_0],
726                         firstPuAMVPCandArray_x[REF_LIST_1],
727                         firstPuAMVPCandArray_y[REF_LIST_1],
728                         firstPuNumAvailableAMVPCand[REF_LIST_1],
729                         pictureControlSetPtr);
730 
731                 }
732 
733                 canTotalCnt++;
734 
735             }
736         }
737     }
738 
739     // update the total number of candidates injected
740     (*candidateTotalCnt) = canTotalCnt;
741 
742 
743     return;
744 }
745 
746 #define BIPRED_3x3_REFINMENT_POSITIONS 8
747 
748 EB_S8 EbHevcBIPRED_3x3_X_POS[BIPRED_3x3_REFINMENT_POSITIONS] = {-1, -1,  0, 1, 1,  1,  0, -1};
749 EB_S8 EbHevcBIPRED_3x3_Y_POS[BIPRED_3x3_REFINMENT_POSITIONS] = { 0,  1,  1, 1, 0, -1, -1, -1};
750 
EbHevcUnipred3x3CandidatesInjection(PictureControlSet_t * pictureControlSetPtr,ModeDecisionContext_t * contextPtr,const SequenceControlSet_t * sequenceControlSetPtr,LargestCodingUnit_t * lcuPtr,const EB_U32 me2Nx2NTableOffset,EB_U32 * candidateTotalCnt,EB_S16 firstPuAMVPCandArray_x[MAX_NUM_OF_REF_PIC_LIST][2],EB_S16 firstPuAMVPCandArray_y[MAX_NUM_OF_REF_PIC_LIST][2],EB_U32 firstPuNumAvailableAMVPCand[MAX_NUM_OF_REF_PIC_LIST])751 void EbHevcUnipred3x3CandidatesInjection(
752 	PictureControlSet_t            *pictureControlSetPtr,
753 	ModeDecisionContext_t          *contextPtr,
754 	const SequenceControlSet_t     *sequenceControlSetPtr,
755 	LargestCodingUnit_t            *lcuPtr,
756 	const EB_U32                    me2Nx2NTableOffset,
757 	EB_U32                         *candidateTotalCnt,
758 	EB_S16                          firstPuAMVPCandArray_x[MAX_NUM_OF_REF_PIC_LIST][2],
759 	EB_S16                          firstPuAMVPCandArray_y[MAX_NUM_OF_REF_PIC_LIST][2],
760 	EB_U32                          firstPuNumAvailableAMVPCand[MAX_NUM_OF_REF_PIC_LIST]
761 )
762 {
763 	EB_U32                   bipredIndex;
764 	EB_U32                   canTotalCnt = (*candidateTotalCnt);
765     EB_BOOL                  mvOutOfPicFlag = EB_FALSE;
766 	const EB_U32             lcuAddr = lcuPtr->index;
767 	const EB_U32             cuOriginX = contextPtr->cuOriginX;
768 	const EB_U32             cuOriginY = contextPtr->cuOriginY;
769 
770 	MeCuResults_t * mePuResult = &pictureControlSetPtr->ParentPcsPtr->meResults[lcuAddr][me2Nx2NTableOffset];
771 	ModeDecisionCandidate_t	*candidateArray = contextPtr->fastCandidateArray;
772 
773 	// (Best_L0, 8 Best_L1 neighbors)
774 	for (bipredIndex = 0; bipredIndex < BIPRED_3x3_REFINMENT_POSITIONS; ++bipredIndex)
775 	{
776 
777 		const EB_U32 interDirection = UNI_PRED_LIST_1;
778 
779 		candidateArray[canTotalCnt].motionVector_x_L0 = mePuResult->xMvL0;
780 		candidateArray[canTotalCnt].motionVector_y_L0 = mePuResult->yMvL0;
781 
782 		candidateArray[canTotalCnt].motionVector_x_L1 = mePuResult->xMvL1 + EbHevcBIPRED_3x3_X_POS[bipredIndex];
783 		candidateArray[canTotalCnt].motionVector_y_L1 = mePuResult->yMvL1 + EbHevcBIPRED_3x3_Y_POS[bipredIndex];
784 
785 		if (pictureControlSetPtr->ParentPcsPtr->useSubpelFlag == 0) {
786 			RoundMv(candidateArray,
787 				canTotalCnt);
788 		}
789 
790         if (sequenceControlSetPtr->staticConfig.unrestrictedMotionVector == 0) {
791             mvOutOfPicFlag = CheckForMvOverBound(
792                         candidateArray[canTotalCnt].motionVector_x_L0,
793                         candidateArray[canTotalCnt].motionVector_y_L0,
794                         contextPtr,
795                         lcuPtr);
796             mvOutOfPicFlag |= CheckForMvOverBound(
797                         candidateArray[canTotalCnt].motionVector_x_L1,
798                         candidateArray[canTotalCnt].motionVector_y_L1,
799                         contextPtr,
800                         lcuPtr);
801             if(mvOutOfPicFlag)
802                 continue;
803         }
804 
805 		candidateArray[canTotalCnt].distortionReady = 0;
806 
807 		candidateArray[canTotalCnt].predictionDirection[0] = (EB_PREDDIRECTION)interDirection;
808 
809 		candidateArray[canTotalCnt].type = INTER_MODE;
810 		candidateArray[canTotalCnt].mergeFlag = EB_FALSE;
811 		if (contextPtr->generateAmvpTableMd == EB_FALSE)
812 		{
813 			// TODO: Clips mvs along with Limit mvs
814 			SetMvpClipMVs(
815 				&candidateArray[canTotalCnt],
816 				cuOriginX,
817 				cuOriginY,
818 				0,
819 				sequenceControlSetPtr->lcuSize,
820 				pictureControlSetPtr
821 			);
822 
823 		}
824 		else
825 		{
826 
827 			ChooseMVPIdx_V2(
828 				&candidateArray[canTotalCnt],
829 				cuOriginX,
830 				cuOriginY,
831 				0,
832 				sequenceControlSetPtr->lcuSize,
833 				firstPuAMVPCandArray_x[REF_LIST_0],
834 				firstPuAMVPCandArray_y[REF_LIST_0],
835 				firstPuNumAvailableAMVPCand[REF_LIST_0],
836 				firstPuAMVPCandArray_x[REF_LIST_1],
837 				firstPuAMVPCandArray_y[REF_LIST_1],
838 				firstPuNumAvailableAMVPCand[REF_LIST_1],
839 				pictureControlSetPtr);
840 
841 		}
842 
843 
844 		canTotalCnt++;
845 	}
846 
847 	// (8 Best_L0 neighbors, Best_L1) :
848 	for (bipredIndex = 0; bipredIndex < BIPRED_3x3_REFINMENT_POSITIONS; ++bipredIndex)
849 	{
850 
851 		const EB_U32 interDirection = UNI_PRED_LIST_0;
852 		candidateArray[canTotalCnt].motionVector_x_L0 = mePuResult->xMvL0 + EbHevcBIPRED_3x3_X_POS[bipredIndex];
853 		candidateArray[canTotalCnt].motionVector_y_L0 = mePuResult->yMvL0 + EbHevcBIPRED_3x3_Y_POS[bipredIndex];
854 		candidateArray[canTotalCnt].motionVector_x_L1 = mePuResult->xMvL1;
855 		candidateArray[canTotalCnt].motionVector_y_L1 = mePuResult->yMvL1;
856 
857 		if (pictureControlSetPtr->ParentPcsPtr->useSubpelFlag == 0) {
858 			RoundMv(candidateArray,
859 				canTotalCnt);
860 		}
861 
862         if (sequenceControlSetPtr->staticConfig.unrestrictedMotionVector == 0) {
863             mvOutOfPicFlag = CheckForMvOverBound(
864                         candidateArray[canTotalCnt].motionVector_x_L0,
865                         candidateArray[canTotalCnt].motionVector_y_L0,
866                         contextPtr,
867                         lcuPtr);
868             mvOutOfPicFlag |= CheckForMvOverBound(
869                         candidateArray[canTotalCnt].motionVector_x_L1,
870                         candidateArray[canTotalCnt].motionVector_y_L1,
871                         contextPtr,
872                         lcuPtr);
873             if(mvOutOfPicFlag)
874                 continue;
875         }
876 
877 		candidateArray[canTotalCnt].distortionReady = 0;
878 
879 		candidateArray[canTotalCnt].predictionDirection[0] = (EB_PREDDIRECTION)interDirection;
880 
881 		candidateArray[canTotalCnt].type = INTER_MODE;
882 		candidateArray[canTotalCnt].mergeFlag = EB_FALSE;
883 		if (contextPtr->generateAmvpTableMd == EB_FALSE)
884 		{
885 			// TODO: Clips mvs along with Limit mvs
886 			SetMvpClipMVs(
887 				&candidateArray[canTotalCnt],
888 				cuOriginX,
889 				cuOriginY,
890 				0,
891 				sequenceControlSetPtr->lcuSize,
892 				pictureControlSetPtr
893 			);
894 
895 		}
896 		else
897 		{
898 
899 			ChooseMVPIdx_V2(
900 				&candidateArray[canTotalCnt],
901 				cuOriginX,
902 				cuOriginY,
903 				0,
904 				sequenceControlSetPtr->lcuSize,
905 				firstPuAMVPCandArray_x[REF_LIST_0],
906 				firstPuAMVPCandArray_y[REF_LIST_0],
907 				firstPuNumAvailableAMVPCand[REF_LIST_0],
908 				firstPuAMVPCandArray_x[REF_LIST_1],
909 				firstPuAMVPCandArray_y[REF_LIST_1],
910 				firstPuNumAvailableAMVPCand[REF_LIST_1],
911 				pictureControlSetPtr);
912 
913 		}
914 
915 
916 		canTotalCnt++;
917 	}
918 
919 	// update the total number of candidates injected
920 	(*candidateTotalCnt) = canTotalCnt;
921 
922 
923 	return;
924 }
925 
EbHevcBipred3x3CandidatesInjection(PictureControlSet_t * pictureControlSetPtr,ModeDecisionContext_t * contextPtr,const SequenceControlSet_t * sequenceControlSetPtr,LargestCodingUnit_t * lcuPtr,const EB_U32 me2Nx2NTableOffset,EB_U32 * candidateTotalCnt,EB_S16 firstPuAMVPCandArray_x[MAX_NUM_OF_REF_PIC_LIST][2],EB_S16 firstPuAMVPCandArray_y[MAX_NUM_OF_REF_PIC_LIST][2],EB_U32 firstPuNumAvailableAMVPCand[MAX_NUM_OF_REF_PIC_LIST])926 void EbHevcBipred3x3CandidatesInjection(
927 	PictureControlSet_t            *pictureControlSetPtr,
928 	ModeDecisionContext_t          *contextPtr,
929 	const SequenceControlSet_t     *sequenceControlSetPtr,
930 	LargestCodingUnit_t            *lcuPtr,
931 	const EB_U32                    me2Nx2NTableOffset,
932 	EB_U32                         *candidateTotalCnt,
933 	EB_S16                          firstPuAMVPCandArray_x[MAX_NUM_OF_REF_PIC_LIST][2],
934 	EB_S16                          firstPuAMVPCandArray_y[MAX_NUM_OF_REF_PIC_LIST][2],
935 	EB_U32                          firstPuNumAvailableAMVPCand[MAX_NUM_OF_REF_PIC_LIST]
936 )
937 {
938 	EB_U32                   bipredIndex;
939 	EB_U32                   canTotalCnt = (*candidateTotalCnt);
940     EB_BOOL                  mvOutOfPicFlag = EB_FALSE;
941 	const EB_U32             lcuAddr = lcuPtr->index;
942 	const EB_U32             cuOriginX = contextPtr->cuOriginX;
943 	const EB_U32             cuOriginY = contextPtr->cuOriginY;
944 
945 	MeCuResults_t * mePuResult = &pictureControlSetPtr->ParentPcsPtr->meResults[lcuAddr][me2Nx2NTableOffset];
946 	ModeDecisionCandidate_t	*candidateArray = contextPtr->fastCandidateArray;
947 
948 
949 	// (Best_L0, 8 Best_L1 neighbors)
950 	for (bipredIndex = 0; bipredIndex < BIPRED_3x3_REFINMENT_POSITIONS; ++bipredIndex)
951 	{
952 
953 		const EB_U32 interDirection = BI_PRED;
954 
955 		candidateArray[canTotalCnt].motionVector_x_L0 = mePuResult->xMvL0;
956 		candidateArray[canTotalCnt].motionVector_y_L0 = mePuResult->yMvL0;
957 
958 		candidateArray[canTotalCnt].motionVector_x_L1 = mePuResult->xMvL1 + EbHevcBIPRED_3x3_X_POS[bipredIndex];
959 		candidateArray[canTotalCnt].motionVector_y_L1 = mePuResult->yMvL1 + EbHevcBIPRED_3x3_Y_POS[bipredIndex];
960 
961 
962 		if (pictureControlSetPtr->ParentPcsPtr->useSubpelFlag == 0) {
963 			RoundMv(candidateArray,
964 				canTotalCnt);
965 		}
966 
967         if (sequenceControlSetPtr->staticConfig.unrestrictedMotionVector == 0) {
968             mvOutOfPicFlag = CheckForMvOverBound(
969                         candidateArray[canTotalCnt].motionVector_x_L0,
970                         candidateArray[canTotalCnt].motionVector_y_L0,
971                         contextPtr,
972                         lcuPtr);
973             mvOutOfPicFlag |= CheckForMvOverBound(
974                         candidateArray[canTotalCnt].motionVector_x_L1,
975                         candidateArray[canTotalCnt].motionVector_y_L1,
976                         contextPtr,
977                         lcuPtr);
978             if(mvOutOfPicFlag)
979                 continue;
980         }
981 
982 		candidateArray[canTotalCnt].distortionReady = 0;
983 
984 		candidateArray[canTotalCnt].predictionDirection[0] = (EB_PREDDIRECTION)interDirection;
985 
986 		candidateArray[canTotalCnt].type = INTER_MODE;
987 		candidateArray[canTotalCnt].mergeFlag = EB_FALSE;
988 		if (contextPtr->generateAmvpTableMd == EB_FALSE)
989 		{
990 			// TODO: Clips mvs along with Limit mvs
991 			SetMvpClipMVs(
992 				&candidateArray[canTotalCnt],
993 				cuOriginX,
994 				cuOriginY,
995 				0,
996 				sequenceControlSetPtr->lcuSize,
997 				pictureControlSetPtr
998 			);
999 
1000 		}
1001 		else
1002 		{
1003 
1004 			ChooseMVPIdx_V2(
1005 				&candidateArray[canTotalCnt],
1006 				cuOriginX,
1007 				cuOriginY,
1008 				0,
1009 				sequenceControlSetPtr->lcuSize,
1010 				firstPuAMVPCandArray_x[REF_LIST_0],
1011 				firstPuAMVPCandArray_y[REF_LIST_0],
1012 				firstPuNumAvailableAMVPCand[REF_LIST_0],
1013 				firstPuAMVPCandArray_x[REF_LIST_1],
1014 				firstPuAMVPCandArray_y[REF_LIST_1],
1015 				firstPuNumAvailableAMVPCand[REF_LIST_1],
1016 				pictureControlSetPtr);
1017 
1018 		}
1019 
1020 
1021 		canTotalCnt++;
1022 	}
1023 
1024 	// (8 Best_L0 neighbors, Best_L1) :
1025 	for (bipredIndex = 0; bipredIndex < BIPRED_3x3_REFINMENT_POSITIONS; ++bipredIndex)
1026 	{
1027 
1028 		const EB_U32 interDirection = BI_PRED;
1029 		candidateArray[canTotalCnt].motionVector_x_L0 = mePuResult->xMvL0 + EbHevcBIPRED_3x3_X_POS[bipredIndex];
1030 		candidateArray[canTotalCnt].motionVector_y_L0 = mePuResult->yMvL0 + EbHevcBIPRED_3x3_Y_POS[bipredIndex];
1031 		candidateArray[canTotalCnt].motionVector_x_L1 = mePuResult->xMvL1;
1032 		candidateArray[canTotalCnt].motionVector_y_L1 = mePuResult->yMvL1;
1033 
1034 
1035 		if (pictureControlSetPtr->ParentPcsPtr->useSubpelFlag == 0) {
1036 			RoundMv(candidateArray,
1037 				canTotalCnt);
1038 		}
1039 
1040         if (sequenceControlSetPtr->staticConfig.unrestrictedMotionVector == 0) {
1041             mvOutOfPicFlag = CheckForMvOverBound(
1042                         candidateArray[canTotalCnt].motionVector_x_L0,
1043                         candidateArray[canTotalCnt].motionVector_y_L0,
1044                         contextPtr,
1045                         lcuPtr);
1046             mvOutOfPicFlag |= CheckForMvOverBound(
1047                         candidateArray[canTotalCnt].motionVector_x_L1,
1048                         candidateArray[canTotalCnt].motionVector_y_L1,
1049                         contextPtr,
1050                         lcuPtr);
1051             if(mvOutOfPicFlag)
1052                 continue;
1053         }
1054 
1055 		candidateArray[canTotalCnt].distortionReady = 0;
1056 
1057 		candidateArray[canTotalCnt].predictionDirection[0] = (EB_PREDDIRECTION)interDirection;
1058 
1059 		candidateArray[canTotalCnt].type = INTER_MODE;
1060 		candidateArray[canTotalCnt].mergeFlag = EB_FALSE;
1061 		if (contextPtr->generateAmvpTableMd == EB_FALSE)
1062 		{
1063 			// TODO: Clips mvs along with Limit mvs
1064 			SetMvpClipMVs(
1065 				&candidateArray[canTotalCnt],
1066 				cuOriginX,
1067 				cuOriginY,
1068 				0,
1069 				sequenceControlSetPtr->lcuSize,
1070 				pictureControlSetPtr
1071 			);
1072 
1073 		}
1074 		else
1075 		{
1076 
1077 			ChooseMVPIdx_V2(
1078 				&candidateArray[canTotalCnt],
1079 				cuOriginX,
1080 				cuOriginY,
1081 				0,
1082 				sequenceControlSetPtr->lcuSize,
1083 				firstPuAMVPCandArray_x[REF_LIST_0],
1084 				firstPuAMVPCandArray_y[REF_LIST_0],
1085 				firstPuNumAvailableAMVPCand[REF_LIST_0],
1086 				firstPuAMVPCandArray_x[REF_LIST_1],
1087 				firstPuAMVPCandArray_y[REF_LIST_1],
1088 				firstPuNumAvailableAMVPCand[REF_LIST_1],
1089 				pictureControlSetPtr);
1090 
1091 		}
1092 
1093 
1094 		canTotalCnt++;
1095 	}
1096 
1097 	// update the total number of candidates injected
1098 	(*candidateTotalCnt) = canTotalCnt;
1099 
1100 	return;
1101 }
1102 
1103 
1104 // END of Function Declarations
ProductIntraCandidateInjection(PictureControlSet_t * pictureControlSetPtr,ModeDecisionContext_t * contextPtr,const SequenceControlSet_t * sequenceControlSetPtr,LargestCodingUnit_t * lcuPtr,EB_U32 * candidateTotalCnt,const EB_U32 leafIndex)1105 void  ProductIntraCandidateInjection(
1106     PictureControlSet_t            *pictureControlSetPtr,
1107     ModeDecisionContext_t          *contextPtr,
1108     const SequenceControlSet_t     *sequenceControlSetPtr,
1109     LargestCodingUnit_t            *lcuPtr,
1110     EB_U32                         *candidateTotalCnt,
1111     const EB_U32                    leafIndex
1112 )
1113 
1114 
1115 {
1116     EB_U32                   openLoopIntraCandidate;
1117     EB_U32                   canTotalCnt = 0;
1118 
1119     const EB_U32             lcuAddr = lcuPtr->index;
1120     const EB_U32             cuSize = contextPtr->cuStats->size;
1121     const EB_U32             cuDepth = contextPtr->cuStats->depth;
1122     const EB_PICTURE           sliceType = pictureControlSetPtr->sliceType;
1123 
1124 
1125     ModeDecisionCandidate_t	*candidateArray = contextPtr->fastCandidateArray;
1126     LcuParams_t				 *lcuParams = &sequenceControlSetPtr->lcuParamsArray[lcuAddr];
1127 
1128     if (contextPtr->intraInjectionMethod == 2) {
1129         EB_U8 totModes = MAX_INTRA_MODES;
1130         for (openLoopIntraCandidate = 0; openLoopIntraCandidate < totModes; ++openLoopIntraCandidate, ++canTotalCnt)
1131         {
1132             candidateArray[canTotalCnt].type = INTRA_MODE;
1133             candidateArray[canTotalCnt].intraLumaMode = openLoopIntraCandidate;
1134             candidateArray[canTotalCnt].distortionReady = 0;
1135         }
1136     }
1137     else {
1138 
1139         const EB_BOOL  isLeftCu = contextPtr->cuStats->originX == 0;
1140         const EB_BOOL  isTopCu = contextPtr->cuStats->originY == 0;
1141         const EB_BOOL  limitIntra = contextPtr->limitIntra;
1142         const EB_U8    limitLeftMode = cuSize < 32 ? EB_INTRA_MODE_27 : EB_INTRA_VERTICAL;
1143         const EB_U8    limitTopMode = cuSize < 32 ? EB_INTRA_MODE_9 : EB_INTRA_HORIZONTAL;
1144 
1145         EB_BOOL skipOis8x8 = (pictureControlSetPtr->ParentPcsPtr->skipOis8x8 && cuSize == 8);
1146 
1147         if (pictureControlSetPtr->ParentPcsPtr->complexLcuArray[lcuPtr->index] == LCU_COMPLEXITY_STATUS_2) {
1148             if (pictureControlSetPtr->ParentPcsPtr->cu8x8Mode == CU_8x8_MODE_1) {
1149                 if (limitIntra == 0 || (isLeftCu == 0 && isTopCu == 0))
1150                 {
1151                     candidateArray[canTotalCnt].type = INTRA_MODE;
1152                     candidateArray[canTotalCnt].intraLumaMode = EB_INTRA_DC;
1153                     candidateArray[canTotalCnt].distortionReady = 0;
1154                     canTotalCnt++;
1155 
1156                     candidateArray[canTotalCnt].type = INTRA_MODE;
1157                     candidateArray[canTotalCnt].intraLumaMode = EB_INTRA_PLANAR;
1158                     candidateArray[canTotalCnt].distortionReady = 0;
1159                 }
1160 
1161             }
1162             else {
1163                 if (skipOis8x8) {
1164                     if (limitIntra == 0 || (isLeftCu == 0 && isTopCu == 0))
1165                     {
1166                         candidateArray[canTotalCnt].type = INTRA_MODE;
1167                         candidateArray[canTotalCnt].intraLumaMode = EB_INTRA_PLANAR;
1168                         candidateArray[canTotalCnt].distortionReady = 0;
1169                         canTotalCnt++;
1170                     }
1171 
1172                 }
1173                 else {
1174 
1175                     const OisCandidate_t *oisCandidate;
1176                     EB_U32 totalIntraLumaMode;
1177 
1178                     if (cuSize > 8)
1179                     {
1180                         const EB_U32 me2Nx2NTableOffset = contextPtr->cuStats->cuNumInDepth + me2Nx2NOffset[contextPtr->cuStats->depth];
1181                         OisCu32Cu16Results_t	        *oisCu32Cu16ResultsPtr = pictureControlSetPtr->ParentPcsPtr->oisCu32Cu16Results[lcuAddr];
1182                         oisCandidate = oisCu32Cu16ResultsPtr->sortedOisCandidate[me2Nx2NTableOffset];
1183                         totalIntraLumaMode = oisCu32Cu16ResultsPtr->totalIntraLumaMode[me2Nx2NTableOffset];
1184 
1185                     }
1186                     else {
1187                         OisCu8Results_t	        *oisCu8ResultsPtr = pictureControlSetPtr->ParentPcsPtr->oisCu8Results[lcuAddr];
1188                         oisCandidate = oisCu8ResultsPtr->sortedOisCandidate[contextPtr->cuStats->cuNumInDepth];
1189                         totalIntraLumaMode = oisCu8ResultsPtr->totalIntraLumaMode[contextPtr->cuStats->cuNumInDepth];
1190                     }
1191 
1192 
1193                     for (openLoopIntraCandidate = 0; openLoopIntraCandidate < totalIntraLumaMode; ++openLoopIntraCandidate)
1194                     {
1195                         const OisCandidate_t *oisCandidatePtr = &oisCandidate[openLoopIntraCandidate];
1196 
1197                         if (limitIntra == 0 || (isLeftCu == 0 && isTopCu == 0))
1198                         {
1199                             if (oisCandidatePtr->intraMode == EB_INTRA_PLANAR || oisCandidatePtr->intraMode == EB_INTRA_DC) {
1200                                 candidateArray[canTotalCnt].oisResults = oisCandidatePtr->oisResults;
1201                                 candidateArray[canTotalCnt].type = INTRA_MODE;
1202                                 canTotalCnt++;
1203                             }
1204                         }
1205                     }
1206                 }
1207             }
1208         }
1209         else {
1210             // No Intra 64x64
1211             if (cuDepth != 0)
1212             {
1213                 //----------------------
1214                 // I Slice
1215                 //----------------------
1216                 if (sliceType == EB_I_PICTURE) {
1217 
1218                     if (cuSize == 32) {
1219                         if (contextPtr->intraInjectionMethod == 1 &&
1220                             DeriveContouringClass(
1221                                 lcuPtr->pictureControlSetPtr->ParentPcsPtr,
1222                                 lcuPtr->index,
1223                                 (EB_U8)leafIndex) == 0) {
1224                             EB_U8 totModes = MAX_INTRA_MODES;
1225                             for (openLoopIntraCandidate = 0; openLoopIntraCandidate < totModes; ++openLoopIntraCandidate, ++canTotalCnt)
1226                             {
1227                                 candidateArray[canTotalCnt].type = INTRA_MODE;
1228                                 candidateArray[canTotalCnt].intraLumaMode = openLoopIntraCandidate;
1229                                 candidateArray[canTotalCnt].distortionReady = 0;
1230                             }
1231                         }
1232                         else {
1233                             EB_U8 totModes = 4;
1234                             for (openLoopIntraCandidate = 0; openLoopIntraCandidate < totModes; ++openLoopIntraCandidate, ++canTotalCnt)
1235                             {
1236                                 candidateArray[canTotalCnt].type = INTRA_MODE;
1237                                 candidateArray[canTotalCnt].intraLumaMode = AntiContouringIntraMode[openLoopIntraCandidate];
1238                                 candidateArray[canTotalCnt].distortionReady = 0;
1239                             }
1240                         }
1241                     }
1242 
1243                     else if (cuSize == 16) {
1244 
1245                         const EB_U32 me2Nx2NTableOffset = contextPtr->cuStats->cuNumInDepth + me2Nx2NOffset[contextPtr->cuStats->depth];
1246                         OisCu32Cu16Results_t	        *oisCu32Cu16ResultsPtr = pictureControlSetPtr->ParentPcsPtr->oisCu32Cu16Results[lcuAddr];
1247                         const OisCandidate_t            *oisCandidate = oisCu32Cu16ResultsPtr->sortedOisCandidate[me2Nx2NTableOffset];
1248                         const EB_U32 totalIntraLumaMode = oisCu32Cu16ResultsPtr->totalIntraLumaMode[me2Nx2NTableOffset];
1249 
1250 
1251                         // Mainline
1252                         if (contextPtr->intraInjectionMethod == 1 &&
1253                             DeriveContouringClass(
1254                                 lcuPtr->pictureControlSetPtr->ParentPcsPtr,
1255                                 lcuPtr->index,
1256                                 (EB_U8)leafIndex) == 0) {
1257 
1258                             EB_U8 totModes = MAX_INTRA_MODES;
1259                             for (openLoopIntraCandidate = 0; openLoopIntraCandidate < totModes; ++openLoopIntraCandidate, ++canTotalCnt)
1260                             {
1261                                 candidateArray[canTotalCnt].type = INTRA_MODE;
1262                                 candidateArray[canTotalCnt].intraLumaMode = openLoopIntraCandidate;
1263                                 candidateArray[canTotalCnt].distortionReady = 0;
1264                             }
1265                         }
1266                         else
1267 
1268                             for (openLoopIntraCandidate = 0; openLoopIntraCandidate < totalIntraLumaMode; ++openLoopIntraCandidate)
1269                             {
1270                                 const OisCandidate_t *oisCandidatePtr = &oisCandidate[openLoopIntraCandidate];
1271 
1272                                 if (AntiContouringIntraModeValidityPerDepth[oisCandidatePtr->intraMode]) {
1273                                     candidateArray[canTotalCnt].oisResults = oisCandidatePtr->oisResults;
1274                                     candidateArray[canTotalCnt].type = INTRA_MODE;
1275                                     candidateArray[canTotalCnt].distortionReady = 0;
1276                                     canTotalCnt++;
1277                                 }
1278 
1279 
1280                             }
1281                     }
1282                     else {
1283 
1284                         OisCu8Results_t	        *oisCu8ResultsPtr = pictureControlSetPtr->ParentPcsPtr->oisCu8Results[lcuAddr];
1285                         const OisCandidate_t    *oisCandidate = oisCu8ResultsPtr->sortedOisCandidate[contextPtr->cuStats->cuNumInDepth];
1286                         const EB_U32 totalIntraLumaMode = oisCu8ResultsPtr->totalIntraLumaMode[contextPtr->cuStats->cuNumInDepth];
1287 
1288 
1289                         // Mainline
1290                         if (contextPtr->intraInjectionMethod == 1) {
1291                             EB_U8 totModes = MAX_INTRA_MODES;
1292                             for (openLoopIntraCandidate = 0; openLoopIntraCandidate < totModes; ++openLoopIntraCandidate, ++canTotalCnt)
1293                             {
1294                                 candidateArray[canTotalCnt].type = INTRA_MODE;
1295                                 candidateArray[canTotalCnt].intraLumaMode = openLoopIntraCandidate;
1296                                 candidateArray[canTotalCnt].distortionReady = 0;
1297                             }
1298                         }
1299                         else {
1300                             for (openLoopIntraCandidate = 0; openLoopIntraCandidate < totalIntraLumaMode; ++openLoopIntraCandidate, ++canTotalCnt)
1301                             {
1302                                 const OisCandidate_t *oisCandidatePtr = &oisCandidate[openLoopIntraCandidate];
1303 
1304                                 candidateArray[canTotalCnt].oisResults = oisCandidatePtr->oisResults;
1305                                 candidateArray[canTotalCnt].type = INTRA_MODE;
1306                                 candidateArray[canTotalCnt].distortionReady = 0;
1307                             }
1308                         }
1309                     }
1310                 }
1311 
1312                 //----------------------
1313                 // P/B Slice
1314                 //----------------------
1315                 else {
1316                     if ((cuSize >= 16 && pictureControlSetPtr->ParentPcsPtr->cu16x16Mode == CU_16x16_MODE_0 &&
1317                         pictureControlSetPtr->encMode < ENC_MODE_11)
1318                          || (cuSize == 32))
1319                     {
1320                         {
1321                             if (pictureControlSetPtr->ParentPcsPtr->limitOisToDcModeFlag)
1322                             {
1323                                 const EB_U32 me2Nx2NTableOffset = contextPtr->cuStats->cuNumInDepth + me2Nx2NOffset[contextPtr->cuStats->depth];
1324                                 const OisCandidate_t            *oisCandidate = pictureControlSetPtr->ParentPcsPtr->oisCu32Cu16Results[lcuAddr]->sortedOisCandidate[me2Nx2NTableOffset];
1325                                 EB_U32							bestSAD;
1326                                 EB_U32                          bestAngMode = 0;
1327 
1328                                 EB_U8 numOfModesToSearch = GetNumOfIntraModesFromOisPoint(
1329                                     pictureControlSetPtr->ParentPcsPtr,
1330                                     (EB_U32)pictureControlSetPtr->ParentPcsPtr->meResults[lcuAddr][me2Nx2NTableOffset].distortionDirection[0].distortion,
1331                                     oisCandidate[0].distortion
1332                                 );
1333 
1334 
1335                                 if (numOfModesToSearch == 1) {
1336 
1337                                     if (limitIntra == 0 || (isLeftCu == 0 && isTopCu == 0))
1338                                     {
1339                                         candidateArray[canTotalCnt].type = INTRA_MODE;
1340                                         candidateArray[canTotalCnt].oisResults = oisCandidate[0].oisResults;//DC
1341                                         canTotalCnt++;
1342                                     }
1343                                 }
1344                                 else {
1345 
1346                                     const EbPictureBufferDesc_t           *inputPicturePtr = pictureControlSetPtr->ParentPcsPtr->enhancedPicturePtr;
1347 
1348                                     intraSearchTheseModesOutputBest(
1349                                         contextPtr,
1350                                         pictureControlSetPtr,
1351                                         inputPicturePtr->bufferY + (contextPtr->cuOriginY + inputPicturePtr->originY) * inputPicturePtr->strideY + (contextPtr->cuOriginX + inputPicturePtr->originX),
1352                                         inputPicturePtr->strideY,
1353                                         numOfModesToSearch,
1354                                         &bestAngMode,
1355                                         &bestSAD);
1356 
1357 
1358                                     if (AntiContouringIntraModeValidityPerDepth[bestAngMode])
1359                                     {
1360                                         candidateArray[canTotalCnt].type = INTRA_MODE;
1361                                         candidateArray[canTotalCnt].intraLumaMode = bestAngMode;
1362                                         candidateArray[canTotalCnt].meDistortion = bestSAD;
1363                                         candidateArray[canTotalCnt].distortionReady = 1;
1364                                         canTotalCnt++;
1365 
1366                                         if (limitIntra == 1)
1367                                             if ((isLeftCu  && bestAngMode != limitLeftMode) || (isTopCu && bestAngMode != limitTopMode))
1368                                                 canTotalCnt--;
1369 
1370                                     }
1371 
1372                                     if (limitIntra == 0 || (isLeftCu == 0 && isTopCu == 0))
1373                                     {
1374                                         candidateArray[canTotalCnt].type = INTRA_MODE;
1375                                         candidateArray[canTotalCnt].intraLumaMode = EB_INTRA_DC;
1376                                         candidateArray[canTotalCnt].distortionReady = 0;
1377                                         canTotalCnt++;
1378 
1379                                         candidateArray[canTotalCnt].type = INTRA_MODE;
1380                                         candidateArray[canTotalCnt].intraLumaMode = EB_INTRA_PLANAR;
1381                                         candidateArray[canTotalCnt].distortionReady = 0;
1382                                         canTotalCnt++;
1383                                     }
1384 
1385                                 }
1386 
1387 
1388                             }
1389                             else {
1390 
1391 
1392                                 const EB_U32 me2Nx2NTableOffset = contextPtr->cuStats->cuNumInDepth + me2Nx2NOffset[contextPtr->cuStats->depth];
1393                                 OisCu32Cu16Results_t	        *oisCu32Cu16ResultsPtr = pictureControlSetPtr->ParentPcsPtr->oisCu32Cu16Results[lcuAddr];
1394                                 const OisCandidate_t            *oisCandidate = oisCu32Cu16ResultsPtr->sortedOisCandidate[me2Nx2NTableOffset];
1395 
1396                                 const EB_U32 totalIntraLumaMode = oisCu32Cu16ResultsPtr->totalIntraLumaMode[me2Nx2NTableOffset];
1397 
1398                                 // Mainline
1399                                 for (openLoopIntraCandidate = 0; openLoopIntraCandidate < totalIntraLumaMode; ++openLoopIntraCandidate)
1400                                 {
1401                                     const OisCandidate_t *oisCandidatePtr = &oisCandidate[openLoopIntraCandidate];
1402 
1403                                     if (AntiContouringIntraModeValidityPerDepth[oisCandidatePtr->intraMode]) {
1404 
1405                                         candidateArray[canTotalCnt].oisResults = oisCandidatePtr->oisResults;
1406                                         candidateArray[canTotalCnt].type = INTRA_MODE;
1407                                         canTotalCnt++;
1408 
1409                                         const EB_U8 iMode = oisCandidatePtr->intraMode;
1410                                         if (limitIntra == 1)
1411                                             if ((isLeftCu  && iMode != limitLeftMode) || (isTopCu && iMode != limitTopMode))
1412                                                 canTotalCnt--;
1413 
1414                                     }
1415 
1416                                 }
1417                             }
1418                         }
1419                     }
1420 
1421 					else if (cuSize == 16) {
1422 					    if (limitIntra == 0 || (isLeftCu == 0 && isTopCu == 0))
1423 						{
1424 							candidateArray[canTotalCnt].type = INTRA_MODE;
1425 							candidateArray[canTotalCnt].intraLumaMode = EB_INTRA_DC;
1426 							candidateArray[canTotalCnt].distortionReady = 0;
1427 							canTotalCnt++;
1428 
1429 							candidateArray[canTotalCnt].type = INTRA_MODE;
1430 							candidateArray[canTotalCnt].intraLumaMode = EB_INTRA_PLANAR;
1431 							candidateArray[canTotalCnt].distortionReady = 0;
1432 							canTotalCnt++;
1433 						}
1434 
1435 					}
1436 
1437                     else if (pictureControlSetPtr->ParentPcsPtr->cu8x8Mode == CU_8x8_MODE_1) {
1438 
1439                         if (skipOis8x8) {
1440                             if (limitIntra == 0 || (isLeftCu == 0 && isTopCu == 0))
1441                             {
1442                                 candidateArray[canTotalCnt].type = INTRA_MODE;
1443                                 candidateArray[canTotalCnt].intraLumaMode = EB_INTRA_PLANAR;
1444                                 candidateArray[canTotalCnt].distortionReady = 0;
1445                                 canTotalCnt++;
1446                             }
1447                         }
1448                         else {
1449 
1450 
1451                             if (lcuParams->isCompleteLcu) {
1452                                 const CodedUnitStats_t  *cuStats = GetCodedUnitStats(EbHevcParentIndex[leafIndex]);
1453                                 const EB_U32 me2Nx2NTableOffset = cuStats->cuNumInDepth + me2Nx2NOffset[cuStats->depth];
1454                                 OisCu32Cu16Results_t	        *oisCu32Cu16ResultsPtr = pictureControlSetPtr->ParentPcsPtr->oisCu32Cu16Results[lcuAddr];
1455                                 const OisCandidate_t    *oisCandidate = oisCu32Cu16ResultsPtr->sortedOisCandidate[me2Nx2NTableOffset];
1456                                 const EB_U32 totalIntraLumaMode = oisCu32Cu16ResultsPtr->totalIntraLumaMode[me2Nx2NTableOffset];
1457 
1458                                 for (openLoopIntraCandidate = 0; openLoopIntraCandidate < totalIntraLumaMode; ++openLoopIntraCandidate)
1459                                 {
1460                                     const OisCandidate_t *oisCandidatePtr = &oisCandidate[openLoopIntraCandidate];
1461                                     if (AntiContouringIntraModeValidityPerDepth[oisCandidatePtr->intraMode]) {
1462                                         if (cuSize < 16 || oisCandidatePtr->intraMode != EB_INTRA_DC) {
1463                                             candidateArray[canTotalCnt].oisResults = oisCandidatePtr->oisResults;
1464                                             candidateArray[canTotalCnt].type = INTRA_MODE;
1465                                             candidateArray[canTotalCnt].distortionReady = 0;
1466                                             ++canTotalCnt;
1467                                             const EB_U8 iMode = oisCandidatePtr->intraMode;
1468                                             if (limitIntra == 1)
1469                                                 if ((isLeftCu  && iMode != limitLeftMode) || (isTopCu && iMode != limitTopMode))
1470                                                     canTotalCnt--;
1471                                         }
1472                                     }
1473                                 }
1474                             }
1475                             else {
1476                                 if (limitIntra == 0 || (isLeftCu == 0 && isTopCu == 0))
1477                                 {
1478                                     // DC
1479                                     candidateArray[canTotalCnt].type = INTRA_MODE;
1480                                     candidateArray[canTotalCnt].intraLumaMode = EB_INTRA_DC;
1481                                     candidateArray[canTotalCnt].distortionReady = 0;
1482                                     canTotalCnt++;
1483                                 }
1484                             }
1485                         }
1486                     }
1487                     else {
1488 
1489                         if (skipOis8x8) {
1490                             if (limitIntra == 0 || (isLeftCu == 0 && isTopCu == 0))
1491                             {
1492                                 candidateArray[canTotalCnt].type = INTRA_MODE;
1493                                 candidateArray[canTotalCnt].intraLumaMode = EB_INTRA_PLANAR;
1494                                 candidateArray[canTotalCnt].distortionReady = 0;
1495                                 canTotalCnt++;
1496 
1497                             }
1498                         }
1499                         else {
1500                             OisCu8Results_t	        *oisCu8ResultsPtr = pictureControlSetPtr->ParentPcsPtr->oisCu8Results[lcuAddr];
1501                             const OisCandidate_t    *oisCandidate = oisCu8ResultsPtr->sortedOisCandidate[contextPtr->cuStats->cuNumInDepth];
1502                             const EB_U32 totalIntraLumaMode = oisCu8ResultsPtr->totalIntraLumaMode[contextPtr->cuStats->cuNumInDepth];
1503 
1504 
1505                             // Mainline
1506                             for (openLoopIntraCandidate = 0; openLoopIntraCandidate < totalIntraLumaMode; ++openLoopIntraCandidate)
1507                             {
1508                                 const OisCandidate_t *oisCandidatePtr = &oisCandidate[openLoopIntraCandidate];
1509 
1510                                 if ((contextPtr->intra8x8RestrictionInterSlice == EB_TRUE && AntiContouringIntraModeValidityPerDepth[oisCandidatePtr->intraMode]) || contextPtr->intra8x8RestrictionInterSlice == EB_FALSE) {
1511 
1512                                     if (cuSize < 16 || oisCandidatePtr->intraMode != EB_INTRA_DC) {
1513                                         candidateArray[canTotalCnt].oisResults = oisCandidatePtr->oisResults;
1514                                         candidateArray[canTotalCnt].type = INTRA_MODE;
1515                                         ++canTotalCnt;
1516 
1517                                         const EB_U8 iMode = oisCandidatePtr->intraMode;
1518                                         if (limitIntra == 1)
1519                                             if ((isLeftCu  && iMode != limitLeftMode) || (isTopCu && iMode != limitTopMode))
1520                                                 canTotalCnt--;
1521                                     }
1522                                 }
1523                             }
1524                         }
1525                     }
1526                 }
1527             }
1528         }
1529     }
1530 
1531     // update the total number of candidates injected
1532     (*candidateTotalCnt) = canTotalCnt;
1533 
1534 
1535     return;
1536 }
1537 
CheckForMvOverBound(EB_S16 mvx,EB_S16 mvy,ModeDecisionContext_t * ctxtPtr,const LargestCodingUnit_t * lcuPtr)1538 static EB_BOOL CheckForMvOverBound(
1539     EB_S16 mvx,
1540     EB_S16 mvy,
1541     ModeDecisionContext_t           *ctxtPtr,
1542     const LargestCodingUnit_t *lcuPtr)
1543 {
1544     EB_S32 mvxF, mvyF;
1545 
1546     //L0
1547     mvxF = (EB_S32)mvx;
1548     mvyF = (EB_S32)mvy;
1549 
1550     EB_S32 cuOriginX = (EB_S32)ctxtPtr->cuOriginX << 2;
1551     EB_S32 cuOriginY = (EB_S32)ctxtPtr->cuOriginY << 2;
1552 
1553     EB_S32 startX = lcuPtr->tileInfoPtr->tilePxlOriginX << 2;
1554     EB_S32 startY = lcuPtr->tileInfoPtr->tilePxlOriginY << 2;
1555     EB_S32 endX   = lcuPtr->tileInfoPtr->tilePxlEndX << 2;
1556     EB_S32 endY   = lcuPtr->tileInfoPtr->tilePxlEndY << 2;
1557     EB_S32 cuSize = (EB_S32)ctxtPtr->cuStats->size << 2;
1558     EB_S32 pad = (4 << 2);
1559 
1560     if (cuOriginX + mvxF + cuSize > (endX - pad)) {
1561 
1562         if (cuOriginX + mvxF + cuSize > endX) {
1563             return EB_TRUE;
1564         }
1565         else {
1566             if (mvxF % 4 != 0 || mvxF % 8 != 0) {
1567                 return EB_TRUE;
1568             }
1569         }
1570     }
1571 
1572     if (cuOriginY + mvyF + cuSize > (endY - pad)) {
1573         if (cuOriginY + mvyF + cuSize > endY) {
1574             return EB_TRUE;
1575         }
1576         else {
1577             if (mvyF % 4 != 0 || mvyF % 8 != 0) {
1578                 return EB_TRUE;
1579             }
1580         }
1581     }
1582 
1583     if (cuOriginX + mvxF < (startX + pad)) {
1584         if (cuOriginX + mvxF < startX) {
1585             return EB_TRUE;
1586         }
1587         else {
1588             if (mvxF % 4 != 0 || mvxF % 8 != 0) {
1589                 return EB_TRUE;
1590             }
1591         }
1592     }
1593 
1594     if (cuOriginY + mvyF < (startY + pad)) {
1595         if (cuOriginY + mvyF < startY) {
1596             return EB_TRUE;
1597         }
1598         else {
1599             if (mvyF % 4 != 0 || mvyF % 8 != 0) {
1600                 return EB_TRUE;
1601             }
1602         }
1603     }
1604 
1605     return EB_FALSE;
1606 }
1607 
ProductMergeSkip2Nx2NCandidatesInjection(ModeDecisionContext_t * contextPtr,const SequenceControlSet_t * sequenceControlSetPtr,LargestCodingUnit_t * lcuPtr,InterPredictionContext_t * interPredictionPtr,EB_U32 * candidateTotalCnt,EB_U32 mvMergeCandidateTotalCount)1608 static void ProductMergeSkip2Nx2NCandidatesInjection(
1609     ModeDecisionContext_t          *contextPtr,
1610     const SequenceControlSet_t     *sequenceControlSetPtr,
1611 	LargestCodingUnit_t			   *lcuPtr,
1612     InterPredictionContext_t       *interPredictionPtr,
1613     EB_U32                         *candidateTotalCnt,
1614     EB_U32                          mvMergeCandidateTotalCount
1615 
1616     )
1617 {
1618     EB_U32                   canTotalCnt                = (*candidateTotalCnt);
1619     EB_U8                    modeDecisionCandidateIndex = 0;
1620     EB_U32                   duplicateIndex;
1621     EB_BOOL                  mvMergeDuplicateFlag       = EB_FALSE;
1622     EB_BOOL                  mvOutOfPicFlag             = EB_FALSE;
1623     ModeDecisionCandidate_t	*candidateArray             = contextPtr->fastCandidateArray;
1624 
1625     while (mvMergeCandidateTotalCount)
1626     {
1627         if (modeDecisionCandidateIndex < interPredictionPtr->mvMergeCandidateCount)
1628         {
1629             const MvMergeCandidate_t *mvMergeCandidatePtr = &interPredictionPtr->mvMergeCandidateArray[modeDecisionCandidateIndex];
1630             const Mv_t *candidateMv = mvMergeCandidatePtr->mv;
1631 
1632             ModeDecisionCandidate_t *mdCandidatePtr = &candidateArray[canTotalCnt];
1633 
1634             // add a duplicate detector to mode decision array
1635             mvMergeDuplicateFlag    = EB_FALSE;
1636             mvOutOfPicFlag          = EB_FALSE;
1637             duplicateIndex          = modeDecisionCandidateIndex;
1638             EB_BOOL duplicateFlags[EB_PREDDIRECTION_TOTAL];
1639             while ((duplicateIndex > 0) && (mvMergeDuplicateFlag == EB_FALSE)) {
1640                 const Mv_t *duplicateMv = interPredictionPtr->mvMergeCandidateArray[--duplicateIndex].mv;
1641 
1642                 duplicateFlags[UNI_PRED_LIST_0] = (EB_BOOL)(candidateMv[REF_LIST_0].mvUnion == duplicateMv[REF_LIST_0].mvUnion);
1643                 duplicateFlags[UNI_PRED_LIST_1] = (EB_BOOL)(mvMergeCandidatePtr->predictionDirection != UNI_PRED_LIST_0 && candidateMv[REF_LIST_1].mvUnion == duplicateMv[REF_LIST_1].mvUnion);
1644                 duplicateFlags[BI_PRED] = (EB_BOOL)(duplicateFlags[UNI_PRED_LIST_0] && duplicateFlags[UNI_PRED_LIST_1]);
1645 
1646                 mvMergeDuplicateFlag = (EB_BOOL)(mvMergeCandidatePtr->predictionDirection == interPredictionPtr->mvMergeCandidateArray[duplicateIndex].predictionDirection && duplicateFlags[mvMergeCandidatePtr->predictionDirection]);
1647             }
1648 
1649             if (sequenceControlSetPtr->staticConfig.unrestrictedMotionVector == 0) {
1650                 if (mvMergeCandidatePtr->predictionDirection == UNI_PRED_LIST_0) {
1651                     mvOutOfPicFlag = CheckForMvOverBound(
1652                         candidateMv[REF_LIST_0].x,
1653                         candidateMv[REF_LIST_0].y,
1654                         contextPtr,
1655                         lcuPtr);
1656                 }
1657                 else if (mvMergeCandidatePtr->predictionDirection == UNI_PRED_LIST_1) {
1658                     mvOutOfPicFlag = CheckForMvOverBound(
1659                         candidateMv[REF_LIST_1].x,
1660                         candidateMv[REF_LIST_1].y,
1661                         contextPtr,
1662                         lcuPtr);
1663                 }
1664                 else {
1665                     mvOutOfPicFlag = CheckForMvOverBound(
1666                         candidateMv[REF_LIST_0].x,
1667                         candidateMv[REF_LIST_0].y,
1668                         contextPtr,
1669                         lcuPtr);
1670                     mvOutOfPicFlag += CheckForMvOverBound(
1671                         candidateMv[REF_LIST_1].x,
1672                         candidateMv[REF_LIST_1].y,
1673                         contextPtr,
1674                         lcuPtr);
1675                 }
1676             }
1677 
1678             if ((sequenceControlSetPtr->staticConfig.unrestrictedMotionVector && mvMergeDuplicateFlag == EB_FALSE) ||
1679                 (!sequenceControlSetPtr->staticConfig.unrestrictedMotionVector && mvMergeDuplicateFlag == EB_FALSE && mvOutOfPicFlag == EB_FALSE)) {
1680                 mdCandidatePtr->type = INTER_MODE;
1681                 mdCandidatePtr->distortionReady = 0;
1682                 //EB_MEMCPY(&mdCandidatePtr->MVs, &candidateMv[REF_LIST_0].x, 8);
1683                 mdCandidatePtr->motionVector_x_L0 = candidateMv[REF_LIST_0].x;
1684                 mdCandidatePtr->motionVector_y_L0 = candidateMv[REF_LIST_0].y;
1685                 mdCandidatePtr->motionVector_x_L1 = candidateMv[REF_LIST_1].x;
1686                 mdCandidatePtr->motionVector_y_L1 = candidateMv[REF_LIST_1].y;
1687                 mdCandidatePtr->mergeFlag = EB_TRUE;
1688                 mdCandidatePtr->mergeIndex = modeDecisionCandidateIndex;
1689                 mdCandidatePtr->mpmFlag = EB_FALSE;
1690                 mdCandidatePtr->predictionDirection[0] = (EB_PREDDIRECTION)mvMergeCandidatePtr->predictionDirection;
1691                 canTotalCnt++;
1692             }
1693 
1694         }
1695 
1696         --mvMergeCandidateTotalCount;
1697         ++modeDecisionCandidateIndex;
1698     }
1699     (*candidateTotalCnt) = canTotalCnt;
1700     return;
1701 }
1702 
ProductMpmCandidatesInjection(ModeDecisionContext_t * contextPtr,EB_U32 * candidateTotalCnt,EB_U32 * bufferTotalCountPtr,EB_BOOL mpmSearch,EB_U8 mpmSearchCandidate,EB_U32 * mostProbableModeArray)1703 void ProductMpmCandidatesInjection(
1704     ModeDecisionContext_t          *contextPtr,
1705     EB_U32                         *candidateTotalCnt,
1706 	EB_U32                         *bufferTotalCountPtr,
1707     EB_BOOL							mpmSearch,
1708 	EB_U8	                        mpmSearchCandidate,
1709 	EB_U32                         *mostProbableModeArray
1710     )
1711 
1712 {
1713     const EB_U32             cuDepth            = contextPtr->cuStats->depth;
1714     EB_U32                   canTotalCnt        = (*candidateTotalCnt);
1715     EB_U32                   fastLoopCandidate  = 0;
1716 	EB_U32                   candidateIndex;
1717 	EB_U32			         mostProbableModeCount;
1718     EB_BOOL                  mpmPresentFlag;
1719 
1720 #ifdef LIMITINRA_MPM_PATCH
1721     const EB_BOOL            cuSize = contextPtr->cuStats->size;
1722     const EB_BOOL            isLeftCu = contextPtr->cuStats->originX == 0;
1723     const EB_BOOL            isTopCu = contextPtr->cuStats->originY == 0;
1724     const EB_BOOL            limitIntra = contextPtr->limitIntra;
1725     const EB_U8              limitLeftMode = cuSize < 32 ? EB_INTRA_MODE_27 : EB_INTRA_VERTICAL;
1726     const EB_U8              limitTopMode = cuSize < 32 ? EB_INTRA_MODE_9 : EB_INTRA_HORIZONTAL;
1727 #endif
1728 
1729     ModeDecisionCandidate_t	*candidateArray     = contextPtr->fastCandidateArray;
1730 
1731     if (mpmSearch && cuDepth != 0){
1732 
1733         fastLoopCandidate = canTotalCnt;
1734 
1735         // Loop over fast loop candidates
1736         for (candidateIndex = 0; candidateIndex < fastLoopCandidate; ++candidateIndex) {
1737             candidateArray[candidateIndex].mpmFlag = EB_FALSE;
1738         }
1739 
1740         // Loop over fast loop candidates
1741         mostProbableModeCount = 0;
1742 
1743         while (mostProbableModeCount < mpmSearchCandidate) {
1744 
1745 #ifdef LIMITINRA_MPM_PATCH
1746             if (!(limitIntra == 0 || (isLeftCu == 0 && isTopCu == 0))) {
1747                 ++mostProbableModeCount;
1748                 continue;
1749             }
1750 #endif
1751             mpmPresentFlag = EB_FALSE;
1752             for (candidateIndex = 0; candidateIndex < fastLoopCandidate; ++candidateIndex) {
1753 
1754                 // Mark MPM mode and add one full loop candidate
1755                 if (candidateArray[candidateIndex].type == INTRA_MODE && mpmPresentFlag == EB_FALSE){
1756 
1757                     if (candidateArray[candidateIndex].intraLumaMode == mostProbableModeArray[mostProbableModeCount]) {
1758 
1759                         candidateArray[candidateIndex].mpmFlag = EB_TRUE;
1760                         ++(*bufferTotalCountPtr);
1761                         mpmPresentFlag = EB_TRUE;
1762                     }
1763                 }
1764             }
1765             // add MPM mode to fast loop and add one full loop candidate
1766             if (mpmPresentFlag == EB_FALSE){
1767                 candidateArray[canTotalCnt].type = INTRA_MODE;
1768                 candidateArray[canTotalCnt].intraLumaMode = mostProbableModeArray[mostProbableModeCount];
1769                 candidateArray[canTotalCnt].distortionReady = 0;
1770                 candidateArray[canTotalCnt].mpmFlag = EB_TRUE;
1771                 canTotalCnt++;
1772                 ++(*bufferTotalCountPtr);
1773             }
1774             ++mostProbableModeCount;
1775         }
1776     }
1777     else {
1778 
1779         // Loop over fast loop candidates
1780         for (candidateIndex = 0; candidateIndex < canTotalCnt; ++candidateIndex) {
1781             candidateArray[candidateIndex].mpmFlag = EB_FALSE;
1782         }
1783     }
1784 
1785     (*candidateTotalCnt) = canTotalCnt;
1786     return;
1787 
1788 }
1789 
1790 /***************************************
1791 * ProductGenerateAmvpMergeInterIntraMdCandidatesCU
1792 *   Creates list of initial modes to
1793 *   perform fast cost search on.
1794 ***************************************/
ProductGenerateAmvpMergeInterIntraMdCandidatesCU(LargestCodingUnit_t * lcuPtr,ModeDecisionContext_t * contextPtr,const EB_U32 leafIndex,const EB_U32 lcuAddr,EB_U32 * bufferTotalCountPtr,EB_U32 * candidateTotalCountPtr,EB_PTR interPredContextPtr,PictureControlSet_t * pictureControlSetPtr,EB_BOOL mpmSearch,EB_U8 mpmSearchCandidate,EB_U32 * mostProbableModeArray)1795 EB_ERRORTYPE ProductGenerateAmvpMergeInterIntraMdCandidatesCU(
1796 	LargestCodingUnit_t				 *lcuPtr,
1797 	ModeDecisionContext_t            *contextPtr,
1798 	const EB_U32                      leafIndex,
1799 	const EB_U32                      lcuAddr,
1800 	EB_U32                           *bufferTotalCountPtr,
1801 	EB_U32                           *candidateTotalCountPtr,
1802 	EB_PTR							  interPredContextPtr,
1803 	PictureControlSet_t              *pictureControlSetPtr,
1804 	EB_BOOL							  mpmSearch,
1805 	EB_U8	                          mpmSearchCandidate,
1806 	EB_U32                           *mostProbableModeArray)
1807 {
1808 	InterPredictionContext_t       *interPredictionPtr  = (InterPredictionContext_t*)interPredContextPtr;
1809 	const SequenceControlSet_t *sequenceControlSetPtr   = (SequenceControlSet_t*)pictureControlSetPtr->sequenceControlSetWrapperPtr->objectPtr;
1810 	// const LargestCodingUnit_t  *lcuPtr = pictureControlSetPtr->lcuPtrArray[lcuAddr];
1811 	const EB_PICTURE sliceType = pictureControlSetPtr->sliceType;
1812 
1813 
1814 	EB_U32 fullReconSearchCount = contextPtr->fullReconSearchCount;
1815 	// AMVP
1816     EB_S16 firstPuAMVPCandArray_x[MAX_NUM_OF_REF_PIC_LIST][2]  ;
1817 	EB_S16 firstPuAMVPCandArray_y[MAX_NUM_OF_REF_PIC_LIST][2]  ;
1818 	EB_U32 firstPuNumAvailableAMVPCand[MAX_NUM_OF_REF_PIC_LIST];
1819 	const EB_U32 cuNumberInDepth = contextPtr->cuStats->cuNumInDepth;
1820     const EB_U32             cuDepth            = contextPtr->cuStats->depth;
1821 	const EB_U32 me2Nx2NTableOffset = cuNumberInDepth + me2Nx2NOffset[cuDepth];
1822 	EB_U32       mvMergeCandidateTotalCount = contextPtr->mvMergeSkipModeCount;
1823 	EB_S16       amvpArray_x[MAX_NUM_OF_REF_PIC_LIST][2];
1824 	EB_S16       amvpArray_y[MAX_NUM_OF_REF_PIC_LIST][2];
1825 	EB_U32       canTotalCnt = 0;
1826 
1827 
1828 	//----------------------
1829 	// Intra
1830 	//----------------------
1831     if (cuDepth != 0 && (sliceType == EB_I_PICTURE || cuDepth == 3 || contextPtr->restrictIntraGlobalMotion == EB_FALSE)) {
1832 		const EB_BOOL  isLeftCu = contextPtr->cuStats->originX == 0;
1833 		const EB_BOOL  isTopCu = contextPtr->cuStats->originY == 0;
1834 		EB_BOOL limitIntraLoptLeft = contextPtr->limitIntra == EB_TRUE && isLeftCu  &&  isTopCu;
1835 		if (limitIntraLoptLeft == 0)
1836 
1837         ProductIntraCandidateInjection( // HT not much to do
1838             pictureControlSetPtr,
1839             contextPtr,
1840             sequenceControlSetPtr,
1841             lcuPtr,
1842             &canTotalCnt,
1843 			leafIndex
1844 			);
1845     }
1846 
1847     if (sliceType != EB_I_PICTURE)
1848     {
1849 
1850         const EB_BOOL tmvpEnableFlag = pictureControlSetPtr->ParentPcsPtr->disableTmvpFlag ? EB_FALSE : EB_TRUE;
1851         //Generate only this number of merge candidates
1852         interPredictionPtr->mvMergeCandidateCount = mvMergeCandidateTotalCount;
1853 
1854         if (contextPtr->conformantMvMergeTable == EB_FALSE && contextPtr->generateAmvpTableMd == EB_FALSE) {
1855             NonConformantGenerateL0L1AmvpMergeLists( // HT not much to do
1856                 contextPtr,
1857                 interPredictionPtr,
1858                 pictureControlSetPtr,
1859                 lcuAddr);
1860         }
1861         else
1862         {
1863             GenerateL0L1AmvpMergeLists(
1864                 contextPtr,
1865                 interPredictionPtr,
1866                 pictureControlSetPtr,
1867                 tmvpEnableFlag,
1868                 lcuAddr,
1869                 amvpArray_x,
1870                 amvpArray_y,
1871                 firstPuNumAvailableAMVPCand,
1872                 firstPuAMVPCandArray_x,
1873                 firstPuAMVPCandArray_y
1874             );
1875         }
1876 
1877         //----------------------
1878         // Me2Nx2N
1879         //----------------------
1880         Me2Nx2NCandidatesInjection( // HT not much to do
1881             pictureControlSetPtr,
1882             contextPtr,
1883             sequenceControlSetPtr,
1884             lcuPtr,
1885             me2Nx2NTableOffset,
1886             &canTotalCnt,
1887             firstPuAMVPCandArray_x,
1888             firstPuAMVPCandArray_y,
1889             firstPuNumAvailableAMVPCand);
1890 
1891 		if (contextPtr->amvpInjection) {
1892 
1893 			//----------------------
1894 			// Amvp2Nx2N
1895 			//----------------------
1896 			Amvp2Nx2NCandidatesInjection(
1897 				pictureControlSetPtr,
1898 				contextPtr,
1899 				sequenceControlSetPtr,
1900 				&canTotalCnt,
1901 				firstPuAMVPCandArray_x,
1902 				firstPuAMVPCandArray_y,
1903 				firstPuNumAvailableAMVPCand);
1904 		}
1905 
1906         if (pictureControlSetPtr->sliceType == EB_B_PICTURE) {
1907             if (contextPtr->bipred3x3Injection) {
1908                 //----------------------
1909                 // Bipred2Nx2N
1910                 //----------------------
1911 
1912                 EbHevcBipred3x3CandidatesInjection( // HT not much to do
1913                     pictureControlSetPtr,
1914                     contextPtr,
1915                     sequenceControlSetPtr,
1916                     lcuPtr,
1917                     me2Nx2NTableOffset,
1918                     &canTotalCnt,
1919                     firstPuAMVPCandArray_x,
1920                     firstPuAMVPCandArray_y,
1921                     firstPuNumAvailableAMVPCand);
1922             }
1923 
1924             if (contextPtr->unipred3x3Injection) {
1925                 //----------------------
1926                 // Unipred2Nx2N
1927                 //----------------------
1928                 EbHevcUnipred3x3CandidatesInjection( // HT not much to do
1929                     pictureControlSetPtr,
1930                     contextPtr,
1931                     sequenceControlSetPtr,
1932                     lcuPtr,
1933                     me2Nx2NTableOffset,
1934                     &canTotalCnt,
1935                     firstPuAMVPCandArray_x,
1936                     firstPuAMVPCandArray_y,
1937                     firstPuNumAvailableAMVPCand);
1938             }
1939         }
1940 
1941 		//----------------------
1942 		// MergeSkip2Nx2N
1943 		//----------------------
1944 		if (mvMergeCandidateTotalCount) {
1945 			ProductMergeSkip2Nx2NCandidatesInjection( // HT not much to do
1946 				contextPtr,
1947 				sequenceControlSetPtr,
1948                 lcuPtr,
1949 				interPredictionPtr,
1950 				&canTotalCnt,
1951 				mvMergeCandidateTotalCount);
1952 		}
1953 
1954 	}
1955 
1956 	// Set BufferTotalCount: determines the number of candidates to fully reconstruct
1957 	*bufferTotalCountPtr = fullReconSearchCount;
1958 
1959 	// Mark MPM candidates, and update the number of full recon - MPM candidates are going to get pushed to the full,
1960 	// however they still need to be tested in the fast loop where the predicted, and the fast rate are going to get computed
1961 #ifdef LIMITINRA_MPM_PATCH
1962     const EB_BOOL  isLeftCu = contextPtr->cuStats->originX == 0;
1963     const EB_BOOL  isTopCu = contextPtr->cuStats->originY == 0;
1964     EB_BOOL limitIntraLoptLeft = contextPtr->limitIntra == EB_TRUE && isLeftCu  &&  isTopCu;
1965     if (limitIntraLoptLeft == 0)
1966 	    ProductMpmCandidatesInjection(
1967 		    contextPtr,
1968 		    &canTotalCnt,
1969 		    bufferTotalCountPtr,
1970 		    mpmSearch,
1971 		    mpmSearchCandidate,
1972 		    mostProbableModeArray);
1973 
1974 #else
1975     ProductMpmCandidatesInjection(
1976         contextPtr,
1977         &canTotalCnt,
1978         bufferTotalCountPtr,
1979         mpmSearch,
1980         mpmSearchCandidate,
1981         mostProbableModeArray);
1982 #endif
1983 
1984 	*candidateTotalCountPtr = canTotalCnt;
1985 
1986 	// Make sure bufferTotalCount is not larger than the number of fast modes
1987 	*bufferTotalCountPtr = MIN(*candidateTotalCountPtr, *bufferTotalCountPtr);
1988 
1989 	return EB_ErrorNone;
1990 }
1991 
1992 /***************************************
1993 * Full Mode Decision
1994 ***************************************/
ProductFullModeDecision(struct ModeDecisionContext_s * contextPtr,CodingUnit_t * cuPtr,EB_U8 cuSize,ModeDecisionCandidateBuffer_t ** bufferPtrArray,EB_U32 candidateTotalCount,EB_U8 * bestCandidateIndexArray,EB_U32 * bestIntraMode)1995 EB_U8 ProductFullModeDecision(
1996     struct ModeDecisionContext_s   *contextPtr,
1997 	CodingUnit_t                   *cuPtr,
1998 	EB_U8                           cuSize,
1999 	ModeDecisionCandidateBuffer_t **bufferPtrArray,
2000 	EB_U32                          candidateTotalCount,
2001 	EB_U8                          *bestCandidateIndexArray,
2002 	EB_U32						   *bestIntraMode)
2003 {
2004 
2005 	EB_U8                   candidateIndex;
2006 	EB_U64                  lowestCost = 0xFFFFFFFFFFFFFFFFull;
2007 	EB_U64                  lowestIntraCost = 0xFFFFFFFFFFFFFFFFull;
2008 	EB_U8                   lowestCostIndex = 0;
2009 	PredictionUnit_t       *puPtr;
2010     EB_U32                   i;
2011 	ModeDecisionCandidate_t       *candidatePtr;
2012 
2013 	lowestCostIndex = bestCandidateIndexArray[0];
2014 
2015 	// Find the candidate with the lowest cost
2016 	for (i = 0; i < candidateTotalCount; ++i) {
2017 
2018 		candidateIndex = bestCandidateIndexArray[i];
2019 
2020 		// Compute fullCostBis
2021 
2022            if (( *(bufferPtrArray[candidateIndex]->fullCostPtr)  < lowestIntraCost) && bufferPtrArray[candidateIndex]->candidatePtr->type == INTRA_MODE){
2023 				*bestIntraMode = bufferPtrArray[candidateIndex]->candidatePtr->intraLumaMode;
2024 				lowestIntraCost = *(bufferPtrArray[candidateIndex]->fullCostPtr);
2025 
2026 			}
2027 
2028 			if ( *(bufferPtrArray[candidateIndex]->fullCostPtr) < lowestCost){
2029 				lowestCostIndex = candidateIndex;
2030 				lowestCost = *(bufferPtrArray[candidateIndex]->fullCostPtr);
2031 			}
2032 
2033 
2034 	}
2035 
2036 	candidatePtr    = bufferPtrArray[lowestCostIndex]->candidatePtr;
2037 
2038 	contextPtr->mdLocalCuUnit[cuPtr->leafIndex].cost = *(bufferPtrArray[lowestCostIndex]->fullCostPtr);
2039 	contextPtr->mdLocalCuUnit[cuPtr->leafIndex].cost      = (contextPtr->mdLocalCuUnit[cuPtr->leafIndex].cost - bufferPtrArray[lowestCostIndex]->candidatePtr->chromaDistortion) + bufferPtrArray[lowestCostIndex]->candidatePtr->chromaDistortionInterDepth;
2040 
2041     if(candidatePtr->type==INTRA_MODE)
2042 		contextPtr->mdLocalCuUnit[cuPtr->leafIndex].costLuma = bufferPtrArray[lowestCostIndex]->fullCostLuma;
2043 	contextPtr->mdEpPipeLcu[cuPtr->leafIndex].mergeCost = *bufferPtrArray[lowestCostIndex]->fullCostMergePtr;
2044 	contextPtr->mdEpPipeLcu[cuPtr->leafIndex].skipCost = *bufferPtrArray[lowestCostIndex]->fullCostSkipPtr;
2045 
2046     if(candidatePtr->type == INTER_MODE && candidatePtr->mergeFlag == EB_TRUE){
2047         contextPtr->mdEpPipeLcu[cuPtr->leafIndex].chromaDistortion = bufferPtrArray[lowestCostIndex]->candidatePtr->chromaDistortion;
2048     }
2049 
2050 	contextPtr->mdLocalCuUnit[cuPtr->leafIndex].fullDistortion = bufferPtrArray[lowestCostIndex]->candidatePtr->fullDistortion;
2051 	contextPtr->mdLocalCuUnit[cuPtr->leafIndex].chromaDistortion = (EB_U32)bufferPtrArray[lowestCostIndex]->candidatePtr->chromaDistortion;
2052 	contextPtr->mdLocalCuUnit[cuPtr->leafIndex].chromaDistortionInterDepth = (EB_U32)bufferPtrArray[lowestCostIndex]->candidatePtr->chromaDistortionInterDepth;
2053 	cuPtr->predictionModeFlag       = candidatePtr->type;
2054     cuPtr->skipFlag                 = candidatePtr->skipFlag; // note, the skip flag is re-checked in the ENCDEC process
2055     cuPtr->rootCbf                  = ((candidatePtr->rootCbf) > 0) ? EB_TRUE : EB_FALSE;
2056 
2057 	contextPtr->mdLocalCuUnit[cuPtr->leafIndex].countNonZeroCoeffs       = candidatePtr->countNonZeroCoeffs;
2058 	// Set the PU level variables
2059 
2060 	{
2061 		puPtr = cuPtr->predictionUnitArray;
2062 		// Intra Prediction
2063 		puPtr->intraLumaMode = 0x1F;
2064 		if (cuPtr->predictionModeFlag == INTRA_MODE)
2065 		{
2066 			puPtr->intraLumaMode = candidatePtr->intraLumaMode;
2067 		}
2068 
2069 		// Inter Prediction
2070 		puPtr->interPredDirectionIndex = candidatePtr->predictionDirection[0];
2071 		puPtr->mergeFlag = candidatePtr->mergeFlag;
2072 		if (cuPtr->predictionModeFlag != INTER_MODE)
2073 		{
2074 			puPtr->interPredDirectionIndex = 0x03;
2075 			puPtr->mergeFlag = EB_FALSE;
2076 		}
2077 		puPtr->mergeIndex = candidatePtr->mergeIndex;
2078 		puPtr->mv[REF_LIST_0].x = 0;
2079 		puPtr->mv[REF_LIST_0].y = 0;
2080 
2081 		puPtr->mv[REF_LIST_1].x = 0;
2082 		puPtr->mv[REF_LIST_1].y = 0;
2083 
2084 		if (puPtr->interPredDirectionIndex == UNI_PRED_LIST_0)
2085 		{
2086 			//EB_MEMCPY(&puPtr->mv[REF_LIST_0].x,&candidatePtr->MVsL0,4);
2087 			puPtr->mv[REF_LIST_0].x = candidatePtr->motionVector_x_L0;
2088 			puPtr->mv[REF_LIST_0].y = candidatePtr->motionVector_y_L0;
2089 		}
2090 
2091 		if (puPtr->interPredDirectionIndex == UNI_PRED_LIST_1)
2092 		{
2093 			//EB_MEMCPY(&puPtr->mv[REF_LIST_1].x,&candidatePtr->MVsL1,4);
2094 			puPtr->mv[REF_LIST_1].x = candidatePtr->motionVector_x_L1;
2095 			puPtr->mv[REF_LIST_1].y = candidatePtr->motionVector_y_L1;
2096 		}
2097 
2098 		if (puPtr->interPredDirectionIndex == BI_PRED)
2099 		{
2100 			//EB_MEMCPY(&puPtr->mv[REF_LIST_0].x,&candidatePtr->MVs,8);
2101 			puPtr->mv[REF_LIST_0].x = candidatePtr->motionVector_x_L0;
2102 			puPtr->mv[REF_LIST_0].y = candidatePtr->motionVector_y_L0;
2103 			puPtr->mv[REF_LIST_1].x = candidatePtr->motionVector_x_L1;
2104 			puPtr->mv[REF_LIST_1].y = candidatePtr->motionVector_y_L1;
2105 		}
2106 
2107         // The MV prediction indicies are recalcated by the EncDec.
2108         puPtr->mvd[REF_LIST_0].predIdx = 0;
2109         puPtr->mvd[REF_LIST_1].predIdx = 0;
2110 
2111 	}
2112 
2113     TransformUnit_t        *tuPtr;
2114 	const TransformUnitStats_t   *tuStatPtr;
2115 	EB_U32                  tuItr;
2116 	EB_U32                  tuSize;
2117 	EB_U32                  tuIndex;
2118 
2119 	EB_U32                  parentTuIndex;
2120 
2121 	EB_U32                  tuTotalCount;
2122 
2123     EB_U32  cuSizeLog2 = contextPtr->cuSizeLog2;
2124 
2125 
2126     if (cuSize == MAX_LCU_SIZE){
2127 		tuTotalCount = 4;
2128 		tuIndex = 1;
2129 		tuItr = 0;
2130 		tuPtr = &cuPtr->transformUnitArray[0];
2131 		tuPtr->splitFlag = EB_TRUE;
2132 		tuPtr->cbCbf = EB_FALSE;
2133 		tuPtr->crCbf = EB_FALSE;
2134 
2135 		// Set TU variables
2136         tuPtr->cbCbf2 = EB_FALSE;
2137         tuPtr->crCbf2 = EB_FALSE;
2138 			tuPtr->chromaCbfContext = 0; //at TU level
2139 		}
2140 		else {
2141 			tuTotalCount = 1;
2142 			tuIndex = 0;
2143 			tuItr = 0;
2144 	}
2145 
2146 	//cuPtr->forceSmallTu = candidatePtr->forceSmallTu;
2147 
2148 	// Set TU
2149 	do {
2150 		tuStatPtr = GetTransformUnitStats(tuIndex);
2151 		tuSize = cuSize >> tuStatPtr->depth;
2152 		tuPtr = &cuPtr->transformUnitArray[tuIndex];
2153 		parentTuIndex = 0;
2154 		if (tuStatPtr->depth > 0)
2155 			parentTuIndex = tuIndexList[tuStatPtr->depth - 1][(tuItr >> 2)];
2156 
2157 		tuPtr->splitFlag = EB_FALSE;
2158 		tuPtr->lumaCbf = (EB_BOOL)(((candidatePtr->yCbf)  & (1 << tuIndex)) > 0);
2159 		tuPtr->cbCbf = (EB_BOOL)(((candidatePtr->cbCbf) & (1 << (tuIndex))) > 0);
2160 		tuPtr->crCbf = (EB_BOOL)(((candidatePtr->crCbf) & (1 << (tuIndex))) > 0);
2161 		tuPtr->cbCbf2 = EB_FALSE;
2162 		tuPtr->crCbf2 = EB_FALSE;
2163 
2164         //CHKN tuPtr->chromaCbfContext = (tuIndex == 0 || (cuPtr->partitionMode == SIZE_NxN)) ? 0 : (cuSizeLog2 - Log2f(tuSize)); //at TU level
2165         tuPtr->chromaCbfContext = (tuIndex == 0 || (0)) ? 0 : (cuSizeLog2 - Log2f(tuSize)); //at TU level
2166 
2167         tuPtr->lumaCbfContext = (cuSizeLog2 - Log2f(tuSize)) == 0 ? 1 : 0;
2168 
2169 		if (tuPtr->cbCbf){
2170 			cuPtr->transformUnitArray[0].cbCbf = EB_TRUE;
2171 			cuPtr->transformUnitArray[parentTuIndex].cbCbf = EB_TRUE;
2172 		}
2173 		if (tuPtr->crCbf){
2174 			cuPtr->transformUnitArray[0].crCbf = EB_TRUE;
2175 			cuPtr->transformUnitArray[parentTuIndex].crCbf = EB_TRUE;
2176 		}
2177 
2178 		++tuItr;
2179 		tuIndex = tuIndexList[tuStatPtr->depth][tuItr];
2180 
2181 	} while (tuItr < tuTotalCount);
2182 
2183 	return lowestCostIndex;
2184 }
2185