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