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