1 /*
2 * Copyright(c) 2018 Intel Corporation
3 * SPDX - License - Identifier: BSD - 2 - Clause - Patent
4 */
5 
6 #include <stdlib.h>
7 #include "EbEntropyCodingProcess.h"
8 #include "EbTransforms.h"
9 #include "EbEncDecResults.h"
10 #include "EbEntropyCodingResults.h"
11 #include "EbRateControlTasks.h"
12 
13 /******************************************************
14  * Enc Dec Context Constructor
15  ******************************************************/
EntropyCodingContextCtor(EntropyCodingContext_t * contextPtr,EbFifo_t * encDecInputFifoPtr,EbFifo_t * packetizationOutputFifoPtr,EbFifo_t * rateControlOutputFifoPtr,EB_BOOL is16bit)16 EB_ERRORTYPE EntropyCodingContextCtor(
17     EntropyCodingContext_t  *contextPtr,
18     EbFifo_t                *encDecInputFifoPtr,
19     EbFifo_t                *packetizationOutputFifoPtr,
20     EbFifo_t                *rateControlOutputFifoPtr,
21     EB_BOOL                  is16bit)
22 {
23     contextPtr->is16bit = is16bit;
24 
25     // Input/Output System Resource Manager FIFOs
26     contextPtr->encDecInputFifoPtr          = encDecInputFifoPtr;
27     //contextPtr->encDecInputFifoPtr->dbg_info = &contextPtr->debug_info;
28     contextPtr->entropyCodingOutputFifoPtr  = packetizationOutputFifoPtr;
29     contextPtr->rateControlOutputFifoPtr    = rateControlOutputFifoPtr;
30 
31     return EB_ErrorNone;
32 }
33 
34 /***********************************************
35  * Entropy Coding Reset Neighbor Arrays
36  ***********************************************/
EntropyCodingResetNeighborArrays(PictureControlSet_t * pictureControlSetPtr,EB_U16 tileIdx)37 static void EntropyCodingResetNeighborArrays(PictureControlSet_t *pictureControlSetPtr, EB_U16 tileIdx)
38 {
39     NeighborArrayUnitReset(pictureControlSetPtr->modeTypeNeighborArray[tileIdx]);
40     NeighborArrayUnitReset(pictureControlSetPtr->leafDepthNeighborArray[tileIdx]);
41     NeighborArrayUnitReset(pictureControlSetPtr->intraLumaModeNeighborArray[tileIdx]);
42     NeighborArrayUnitReset(pictureControlSetPtr->skipFlagNeighborArray[tileIdx]);
43 
44     return;
45 }
46 
47 /**************************************************
48  * Reset Entropy Coding Picture
49  **************************************************/
ResetEntropyCodingPicture(EntropyCodingContext_t * contextPtr,PictureControlSet_t * pictureControlSetPtr,SequenceControlSet_t * sequenceControlSetPtr)50 static void ResetEntropyCodingPicture(
51 	EntropyCodingContext_t  *contextPtr,
52 	PictureControlSet_t     *pictureControlSetPtr,
53 	SequenceControlSet_t    *sequenceControlSetPtr)
54 {
55     EB_U32 tileCnt = pictureControlSetPtr->ParentPcsPtr->tileRowCount * pictureControlSetPtr->ParentPcsPtr->tileColumnCount;
56     EB_U32 tileIdx = 0;
57 
58     for (tileIdx = 0; tileIdx < tileCnt; tileIdx++) {
59         ResetBitstream(EntropyCoderGetBitstreamPtr(pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCoderPtr));
60     }
61 
62 	EB_U32                       entropyCodingQp;
63 
64 	contextPtr->is16bit = (EB_BOOL)(sequenceControlSetPtr->staticConfig.encoderBitDepth > EB_8BIT);
65 
66 	// SAO
67 	pictureControlSetPtr->saoFlag[0] = EB_TRUE;
68 	pictureControlSetPtr->saoFlag[1] = EB_TRUE;
69 
70 	// QP
71 	contextPtr->qp = pictureControlSetPtr->pictureQp;
72 	// Asuming cb and cr offset to be the same for chroma QP in both slice and pps for lambda computation
73 
74 	EB_U8	qpScaled = CLIP3((EB_S8)MIN_QP_VALUE, (EB_S8)MAX_CHROMA_MAP_QP_VALUE, (EB_S8)(contextPtr->qp + pictureControlSetPtr->cbQpOffset + pictureControlSetPtr->sliceCbQpOffset));
75 	contextPtr->chromaQp = MapChromaQp(qpScaled);
76 
77 
78 	if (pictureControlSetPtr->useDeltaQp) {
79 		entropyCodingQp = pictureControlSetPtr->pictureQp;
80 	}
81 	else {
82 		entropyCodingQp = pictureControlSetPtr->pictureQp;
83 	}
84 
85 
86 	// Reset CABAC Contexts
87 	// Reset QP Assignement
88     for (tileIdx = 0; tileIdx < tileCnt; tileIdx++) {
89         pictureControlSetPtr->prevCodedQp[tileIdx] = pictureControlSetPtr->pictureQp;
90         pictureControlSetPtr->prevQuantGroupCodedQp[tileIdx] = pictureControlSetPtr->pictureQp;
91 
92         ResetEntropyCoder(
93                 sequenceControlSetPtr->encodeContextPtr,
94                 pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCoderPtr,
95                 entropyCodingQp,
96                 pictureControlSetPtr->sliceType);
97 
98         EntropyCodingResetNeighborArrays(pictureControlSetPtr, tileIdx);
99     }
100 
101 
102     return;
103 }
104 
105 
106 /******************************************************
107  * EncDec Configure LCU
108  ******************************************************/
EntropyCodingConfigureLcu(EntropyCodingContext_t * contextPtr,LargestCodingUnit_t * lcuPtr,PictureControlSet_t * pictureControlSetPtr)109 static void EntropyCodingConfigureLcu(
110     EntropyCodingContext_t  *contextPtr,
111     LargestCodingUnit_t     *lcuPtr,
112     PictureControlSet_t     *pictureControlSetPtr)
113 {
114     contextPtr->qp = pictureControlSetPtr->pictureQp;
115 
116 	// Asuming cb and cr offset to be the same for chroma QP in both slice and pps for lambda computation
117 
118 	EB_U8	qpScaled = CLIP3((EB_S8)MIN_QP_VALUE, (EB_S8)MAX_CHROMA_MAP_QP_VALUE, (EB_S8)(contextPtr->qp + pictureControlSetPtr->cbQpOffset + pictureControlSetPtr->sliceCbQpOffset));
119 	contextPtr->chromaQp = MapChromaQp(qpScaled);
120 
121     lcuPtr->qp = contextPtr->qp;
122 
123     return;
124 }
125 
126 /******************************************************
127  * Entropy Coding Lcu
128  ******************************************************/
EntropyCodingLcu(LargestCodingUnit_t * lcuPtr,PictureControlSet_t * pictureControlSetPtr,SequenceControlSet_t * sequenceControlSetPtr,EB_U32 lcuOriginX,EB_U32 lcuOriginY,EB_BOOL terminateSliceFlag,EB_U16 tileIdx,EB_U32 pictureOriginX,EB_U32 pictureOriginY)129 static void EntropyCodingLcu(
130     LargestCodingUnit_t               *lcuPtr,
131     PictureControlSet_t               *pictureControlSetPtr,
132     SequenceControlSet_t              *sequenceControlSetPtr,
133     EB_U32                             lcuOriginX,
134     EB_U32                             lcuOriginY,
135     EB_BOOL                            terminateSliceFlag,
136     EB_U16                             tileIdx,
137     EB_U32                             pictureOriginX,
138     EB_U32                             pictureOriginY)
139 {
140 
141 	EbPictureBufferDesc_t *coeffPicturePtr = lcuPtr->quantizedCoeff;
142 
143     //rate Control
144     EB_U32                       writtenBitsBeforeQuantizedCoeff;
145     EB_U32                       writtenBitsAfterQuantizedCoeff;
146     EntropyCoder_t               *entropyCoderPtr = pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCoderPtr;
147     //store the number of written bits before coding quantized coeffs (flush is not called yet):
148     // The total number of bits is
149     // number of written bits
150     // + 32  - bits remaining in interval Low Value
151     // + number of buffered byte * 8
152     // This should be only for coeffs not any flag
153     writtenBitsBeforeQuantizedCoeff =  ((OutputBitstreamUnit_t*)EntropyCoderGetBitstreamPtr(entropyCoderPtr))->writtenBitsCount +
154                                         32 - ((CabacEncodeContext_t*) entropyCoderPtr->cabacEncodeContextPtr)->bacEncContext.bitsRemainingNum +
155                                         (((CabacEncodeContext_t*)entropyCoderPtr->cabacEncodeContextPtr)->bacEncContext.tempBufferedBytesNum <<3);
156 
157     if(sequenceControlSetPtr->staticConfig.enableSaoFlag && (pictureControlSetPtr->saoFlag[0] || pictureControlSetPtr->saoFlag[1])) {
158 
159         // Code SAO parameters
160         EncodeLcuSaoParameters(
161             lcuPtr,
162             entropyCoderPtr,
163             pictureControlSetPtr->saoFlag[0],
164             pictureControlSetPtr->saoFlag[1],
165             (EB_U8)sequenceControlSetPtr->staticConfig.encoderBitDepth);
166     }
167 
168     EncodeLcu(
169         lcuPtr,
170         lcuOriginX,
171         lcuOriginY,
172         pictureControlSetPtr,
173         sequenceControlSetPtr->lcuSize,
174         entropyCoderPtr,
175         coeffPicturePtr,
176         pictureControlSetPtr->modeTypeNeighborArray[tileIdx],
177         pictureControlSetPtr->leafDepthNeighborArray[tileIdx],
178         pictureControlSetPtr->intraLumaModeNeighborArray[tileIdx],
179         pictureControlSetPtr->skipFlagNeighborArray[tileIdx],
180         tileIdx,
181 		pictureOriginX,
182 		pictureOriginY);
183 
184     //Jing:TODO
185     // extend the totalBits to tile, for tile based brc
186 
187     //store the number of written bits after coding quantized coeffs (flush is not called yet):
188     // The total number of bits is
189     // number of written bits
190     // + 32  - bits remaining in interval Low Value
191     // + number of buffered byte * 8
192     writtenBitsAfterQuantizedCoeff =   ((OutputBitstreamUnit_t*)EntropyCoderGetBitstreamPtr(entropyCoderPtr))->writtenBitsCount +
193                                         32 - ((CabacEncodeContext_t*) entropyCoderPtr->cabacEncodeContextPtr)->bacEncContext.bitsRemainingNum +
194                                         (((CabacEncodeContext_t*) entropyCoderPtr->cabacEncodeContextPtr)->bacEncContext.tempBufferedBytesNum <<3);
195 
196     lcuPtr->totalBits = writtenBitsAfterQuantizedCoeff - writtenBitsBeforeQuantizedCoeff;
197 
198     pictureControlSetPtr->ParentPcsPtr->quantizedCoeffNumBits += lcuPtr->quantizedCoeffsBits;
199 
200     /*********************************************************
201     *Note - At the end of each LCU, HEVC adds 1 bit to indicate that
202     if the current LCU is the end of a slice, where 0x1 means it is the
203     end of slice and 0x0 means not. Currently we assume that each slice
204     contains integer number of tiles, thus the trailing 1 bit for the
205     non-ending LCU of a tile is always 0x0 and the trailing 1 bit for the
206     tile ending LCU can be 0x0 or 0x1. In the entropy coding process, we
207     can not decide the slice boundary so we can not write the trailing 1 bit
208     for the tile ending LCU.
209     *********************************************************/
210     EncodeTerminateLcu(
211         entropyCoderPtr,
212         terminateSliceFlag);
213 
214     return;
215 }
216 
217 /******************************************************
218  * Update Entropy Coding Rows
219  *
220  * This function is responsible for synchronizing the
221  *   processing of Entropy Coding LCU-rows and starts
222  *   processing of LCU-rows as soon as their inputs are
223  *   available and the previous LCU-row has completed.
224  *   At any given time, only one segment row per picture
225  *   is being processed.
226  *
227  * The function has two parts:
228  *
229  * (1) Update the available row index which tracks
230  *   which LCU Row-inputs are available.
231  *
232  * (2) Increment the lcu-row counter as the segment-rows
233  *   are completed.
234  *
235  * Since there is the potentential for thread collusion,
236  *   a MUTEX a used to protect the sensitive data and
237  *   the execution flow is separated into two paths
238  *
239  * (A) Initial update.
240  *  -Update the Completion Mask [see (1) above]
241  *  -If the picture is not currently being processed,
242  *     check to see if the next segment-row is available
243  *     and start processing.
244  * (B) Continued processing
245  *  -Upon the completion of a segment-row, check
246  *     to see if the next segment-row's inputs have
247  *     become available and begin processing if so.
248  *
249  * On last important point is that the thread-safe
250  *   code section is kept minimally short. The MUTEX
251  *   should NOT be locked for the entire processing
252  *   of the segment-row (B) as this would block other
253  *   threads from performing an update (A).
254  ******************************************************/
UpdateEntropyCodingRows(PictureControlSet_t * pictureControlSetPtr,EB_U32 * rowIndex,EB_U32 rowCount,EB_U32 tileIdx,EB_BOOL * initialProcessCall)255 static EB_BOOL UpdateEntropyCodingRows(
256     PictureControlSet_t *pictureControlSetPtr,
257     EB_U32              *rowIndex,
258     EB_U32               rowCount,
259     EB_U32               tileIdx,
260     EB_BOOL             *initialProcessCall)
261 {
262     EB_BOOL processNextRow = EB_FALSE;
263 
264     EntropyTileInfo *infoPtr = pictureControlSetPtr->entropyCodingInfo[tileIdx];
265     // Note, any writes & reads to status variables (e.g. inProgress) in MD-CTRL must be thread-safe
266     EbBlockOnMutex(infoPtr->entropyCodingMutex);
267 
268     // Update availability mask
269     if (*initialProcessCall == EB_TRUE) {
270         unsigned i;
271 
272         for(i=*rowIndex; i < *rowIndex + rowCount; ++i) {
273             infoPtr->entropyCodingRowArray[i] = EB_TRUE;
274         }
275 
276         while(infoPtr->entropyCodingRowArray[infoPtr->entropyCodingCurrentAvailableRow] == EB_TRUE &&
277               infoPtr->entropyCodingCurrentAvailableRow < infoPtr->entropyCodingRowCount)
278         {
279             ++infoPtr->entropyCodingCurrentAvailableRow;
280         }
281     }
282 
283     // Release inProgress token
284     if(*initialProcessCall == EB_FALSE && infoPtr->entropyCodingInProgress == EB_TRUE) {
285         infoPtr->entropyCodingInProgress = EB_FALSE;
286     }
287 
288     // Test if the picture is not already complete AND not currently being worked on by another ENCDEC process
289     if(infoPtr->entropyCodingCurrentRow < infoPtr->entropyCodingRowCount &&
290        infoPtr->entropyCodingRowArray[infoPtr->entropyCodingCurrentRow] == EB_TRUE &&
291        infoPtr->entropyCodingInProgress == EB_FALSE)
292     {
293         // Test if the next LCU-row is ready to go
294         if(infoPtr->entropyCodingCurrentRow <= infoPtr->entropyCodingCurrentAvailableRow)
295         {
296             infoPtr->entropyCodingInProgress = EB_TRUE;
297             *rowIndex = infoPtr->entropyCodingCurrentRow++;
298             processNextRow = EB_TRUE;
299         }
300     }
301 
302     *initialProcessCall = EB_FALSE;
303 
304     EbReleaseMutex(infoPtr->entropyCodingMutex);
305 
306     return processNextRow;
307 }
308 
309 
310 /******************************************************
311  * Entropy Coding Kernel
312  ******************************************************/
EntropyCodingKernel(void * inputPtr)313 void* EntropyCodingKernel(void *inputPtr)
314 {
315     // Context & SCS & PCS
316     EntropyCodingContext_t                  *contextPtr = (EntropyCodingContext_t*) inputPtr;
317     PictureControlSet_t                     *pictureControlSetPtr;
318     SequenceControlSet_t                    *sequenceControlSetPtr;
319 
320     // Input
321     EbObjectWrapper_t                       *encDecResultsWrapperPtr;
322     EncDecResults_t                         *encDecResultsPtr;
323 
324     // Output
325     EbObjectWrapper_t                       *entropyCodingResultsWrapperPtr;
326     EntropyCodingResults_t                  *entropyCodingResultsPtr;
327 
328     // LCU Loop variables
329     LargestCodingUnit_t                     *lcuPtr;
330     EB_U16                                   lcuIndex;
331     EB_U8                                    lcuSize;
332     EB_U8                                    lcuSizeLog2;
333     EB_U32                                   xLcuIndex;
334     EB_U32                                   yLcuIndex;
335     EB_U32                                   lcuOriginX;
336     EB_U32                                   lcuOriginY;
337     EB_BOOL                                  lastLcuFlagInSlice;
338     EB_BOOL                                  lastLcuFlagInTile;
339     EB_U32                                   pictureWidthInLcu;
340     EB_U32                                   tileWidthInLcu;
341     EB_U32                                   tileHeightInLcu;
342     // Variables
343     EB_BOOL                                  initialProcessCall;
344     EB_U32                                   tileIdx;
345     EB_U16                                   tileRowIdx;
346     EB_U16                                   tileColIdx;
347     EB_U32                                   tileCnt;
348     EB_U32                                   xLcuStart;
349     EB_U32                                   yLcuStart;
350 
351     for(;;) {
352 
353         // Get Mode Decision Results
354         EbGetFullObject(
355             contextPtr->encDecInputFifoPtr,
356             &encDecResultsWrapperPtr);
357         EB_CHECK_END_OBJ(encDecResultsWrapperPtr);
358         encDecResultsPtr       = (EncDecResults_t*) encDecResultsWrapperPtr->objectPtr;
359         pictureControlSetPtr   = (PictureControlSet_t*) encDecResultsPtr->pictureControlSetWrapperPtr->objectPtr;
360         sequenceControlSetPtr  = (SequenceControlSet_t*) pictureControlSetPtr->sequenceControlSetWrapperPtr->objectPtr;
361         tileIdx                = encDecResultsPtr->tileIndex;
362         tileRowIdx             = tileIdx / pictureControlSetPtr->ParentPcsPtr->tileColumnCount;
363         tileColIdx             = tileIdx % pictureControlSetPtr->ParentPcsPtr->tileColumnCount;
364         lastLcuFlagInSlice     = EB_FALSE;
365         lastLcuFlagInTile      = EB_FALSE;
366         tileCnt                = pictureControlSetPtr->ParentPcsPtr->tileRowCount * pictureControlSetPtr->ParentPcsPtr->tileColumnCount;
367 #if DEADLOCK_DEBUG
368         if ((pictureControlSetPtr->pictureNumber >= MIN_POC) && (pictureControlSetPtr->pictureNumber <= MAX_POC))
369             if (pictureControlSetPtr->encDecCodedLcuCount == pictureControlSetPtr->lcuTotalCount)
370                 SVT_LOG("POC %lu EC IN \n", pictureControlSetPtr->pictureNumber);
371 #endif
372         //SVT_LOG("[%lld]: POC %lld EC IN, tile %d, (%d, %d) \n",
373         //        EbGetSysTimeMs(),
374         //        pictureControlSetPtr->pictureNumber, tileIdx,
375         //        encDecResultsPtr->completedLcuRowIndexStart,
376         //        encDecResultsPtr->completedLcuRowIndexStart + encDecResultsPtr->completedLcuRowCount);
377         // LCU Constants
378         lcuSize     = sequenceControlSetPtr->lcuSize;
379         lcuSizeLog2 = (EB_U8)Log2f(lcuSize);
380         contextPtr->lcuSize = lcuSize;
381         pictureWidthInLcu = pictureControlSetPtr->ParentPcsPtr->pictureWidthInLcu;
382 
383         tileWidthInLcu = pictureControlSetPtr->ParentPcsPtr->tileColStartLcu[tileColIdx + 1] - pictureControlSetPtr->ParentPcsPtr->tileColStartLcu[tileColIdx];
384         tileHeightInLcu = pictureControlSetPtr->ParentPcsPtr->tileRowStartLcu[tileRowIdx + 1] - pictureControlSetPtr->ParentPcsPtr->tileRowStartLcu[tileRowIdx];
385         xLcuStart = pictureControlSetPtr->ParentPcsPtr->tileColStartLcu[tileColIdx];
386         yLcuStart = pictureControlSetPtr->ParentPcsPtr->tileRowStartLcu[tileRowIdx];
387 
388         {
389             initialProcessCall = EB_TRUE;
390             yLcuIndex = encDecResultsPtr->completedLcuRowIndexStart;
391 
392             // LCU-loops
393             while(UpdateEntropyCodingRows(pictureControlSetPtr, &yLcuIndex, encDecResultsPtr->completedLcuRowCount, tileIdx, &initialProcessCall) == EB_TRUE)
394             {
395                 EB_U32 rowTotalBits = 0;
396 
397                 if(yLcuIndex == 0) {
398                     EbBlockOnMutex(pictureControlSetPtr->entropyCodingPicMutex);
399                     if (pictureControlSetPtr->entropyCodingPicResetFlag) {
400                         //printf("[%lld]:Reset pic %d at tile %d, yLcuIndex is %d\n",
401                         //        EbGetSysTimeMs(),
402                         //        pictureControlSetPtr->pictureNumber, tileIdx, yLcuIndex + yLcuStart);
403                         pictureControlSetPtr->entropyCodingPicResetFlag = EB_FALSE;
404                         ResetEntropyCodingPicture(
405                                 contextPtr,
406                                 pictureControlSetPtr,
407                                 sequenceControlSetPtr);
408                     }
409                     EbReleaseMutex(pictureControlSetPtr->entropyCodingPicMutex);
410 					pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCodingPicDone = EB_FALSE;
411                 }
412 
413                 for(xLcuIndex = 0; xLcuIndex < tileWidthInLcu; ++xLcuIndex) {
414                     lcuIndex = (EB_U16)((xLcuIndex + xLcuStart) + (yLcuIndex + yLcuStart) * pictureWidthInLcu);
415                     lcuPtr = pictureControlSetPtr->lcuPtrArray[lcuIndex];
416 
417                     lcuOriginX = (xLcuIndex + xLcuStart) << lcuSizeLog2;
418                     lcuOriginY = (yLcuIndex + yLcuStart) << lcuSizeLog2;
419                     //Jing:
420                     //Check for lastLcu, since tiles are parallelized, last LCU may not be the the last one in slice
421                     lastLcuFlagInSlice = (lcuIndex == pictureControlSetPtr->lcuTotalCount - 1) ? EB_TRUE : EB_FALSE;
422                     lastLcuFlagInTile = (xLcuIndex == tileWidthInLcu - 1 && yLcuIndex == tileHeightInLcu - 1) ? EB_TRUE : EB_FALSE;
423                     if (sequenceControlSetPtr->staticConfig.tileSliceMode) {
424                         lastLcuFlagInSlice = lastLcuFlagInTile;
425                     }
426 
427                     // Configure the LCU
428                     EntropyCodingConfigureLcu(
429                         contextPtr,
430                         lcuPtr,
431                         pictureControlSetPtr);
432 
433                     // Entropy Coding
434                     EntropyCodingLcu(
435                         lcuPtr,
436                         pictureControlSetPtr,
437                         sequenceControlSetPtr,
438                         lcuOriginX,
439                         lcuOriginY,
440                         lastLcuFlagInSlice,
441                         tileIdx,
442                         (xLcuIndex + xLcuStart) * lcuSize,
443                         (yLcuIndex + yLcuStart) * lcuSize);
444 
445                     rowTotalBits += lcuPtr->totalBits;
446                 }
447 
448                 // At the end of each LCU-row, send the updated bit-count to Entropy Coding
449                 {
450                     //Jing: TODO
451                     //this is per tile, brc can use it or just ignore it
452                     EbObjectWrapper_t *rateControlTaskWrapperPtr;
453                     RateControlTasks_t *rateControlTaskPtr;
454 
455                     // Get Empty EncDec Results
456                     EbGetEmptyObject(
457                         contextPtr->rateControlOutputFifoPtr,
458                         &rateControlTaskWrapperPtr);
459                     rateControlTaskPtr = (RateControlTasks_t*) rateControlTaskWrapperPtr->objectPtr;
460                     rateControlTaskPtr->taskType = RC_ENTROPY_CODING_ROW_FEEDBACK_RESULT;
461                     rateControlTaskPtr->pictureNumber = pictureControlSetPtr->pictureNumber;
462                     rateControlTaskPtr->tileIndex = tileIdx;
463                     rateControlTaskPtr->rowNumber = yLcuIndex; //Jing: yLcuIndex within tile
464                     rateControlTaskPtr->bitCount = rowTotalBits;
465 
466                     rateControlTaskPtr->pictureControlSetWrapperPtr = 0;
467                     rateControlTaskPtr->segmentIndex = ~0u;
468 
469                     // Post EncDec Results
470                     EbPostFullObject(rateControlTaskWrapperPtr);
471                 }
472 
473 				EbBlockOnMutex(pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCodingMutex);
474 				if (pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCodingPicDone == EB_FALSE) {
475                     //Jing: Store the av(e) part for different tiles and copy it as a whole to slice bitstream
476 
477 					// If the picture is complete, terminate the slice
478 					if (pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCodingCurrentRow == pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCodingRowCount)
479 					{
480                         EB_BOOL pic_ready = EB_TRUE;
481 
482                         //assert(lastLcuFlagInTile == EB_TRUE);
483 
484                         //Jing:tile end, may not be the slice end
485                         if (!lastLcuFlagInSlice) {
486                             //printf("[%lld]:Encode tile end for tile %d\n", EbGetSysTimeMs(), tileIdx);
487                             EncodeTileFinish(pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCoderPtr);
488                         } else {
489                             //printf("[%lld]:Encode slice end for tile %d\n", EbGetSysTimeMs(), tileIdx);
490 						    EncodeSliceFinish(pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCoderPtr);
491                         }
492 
493                         //Jing: TODO
494                         //Release the ref if the whole pic are done
495                         EbBlockOnMutex(pictureControlSetPtr->entropyCodingPicMutex);
496 						pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCodingPicDone = EB_TRUE;
497                         for (EB_U32 i = 0; i < tileCnt; i++) {
498                             if (pictureControlSetPtr->entropyCodingInfo[i]->entropyCodingPicDone == EB_FALSE) {
499                                 pic_ready = EB_FALSE;
500                                 //printf("current POC %d not fully ready, tile %d missing\n", pictureControlSetPtr->pictureNumber, i);
501                                 break;
502                             }
503                         }
504                         EbReleaseMutex(pictureControlSetPtr->entropyCodingPicMutex);
505 
506                         if (pic_ready) {
507                             // Get Empty Entropy Coding Results
508                             EbGetEmptyObject(
509                                     contextPtr->entropyCodingOutputFifoPtr,
510                                     &entropyCodingResultsWrapperPtr);
511                             entropyCodingResultsPtr = (EntropyCodingResults_t*)entropyCodingResultsWrapperPtr->objectPtr;
512                             entropyCodingResultsPtr->pictureControlSetWrapperPtr = encDecResultsPtr->pictureControlSetWrapperPtr;
513 
514                             //SVT_LOG("[%lld]: Entropy post result, POC %d\n", EbGetSysTimeMs(), pictureControlSetPtr->pictureNumber);
515                             // Post EntropyCoding Results
516                             EbPostFullObject(entropyCodingResultsWrapperPtr);
517 
518 #if DEADLOCK_DEBUG
519                             if ((pictureControlSetPtr->pictureNumber >= MIN_POC) && (pictureControlSetPtr->pictureNumber <= MAX_POC))
520                                 SVT_LOG("POC %lu EC OUT \n", pictureControlSetPtr->pictureNumber);
521 #endif
522                         }
523 					} // End if(PictureCompleteFlag)
524 				}
525 				EbReleaseMutex(pictureControlSetPtr->entropyCodingInfo[tileIdx]->entropyCodingMutex);
526 			}
527         }
528         // Release Mode Decision Results
529         EbReleaseObject(encDecResultsWrapperPtr);
530 
531     }
532 
533     return EB_NULL;
534 }
535