• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*!
2  * \copy
3  *     Copyright (c)  2009-2013, Cisco Systems
4  *     All rights reserved.
5  *
6  *     Redistribution and use in source and binary forms, with or without
7  *     modification, are permitted provided that the following conditions
8  *     are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *
13  *        * Redistributions in binary form must reproduce the above copyright
14  *          notice, this list of conditions and the following disclaimer in
15  *          the documentation and/or other materials provided with the
16  *          distribution.
17  *
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26  *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  *     POSSIBILITY OF SUCH DAMAGE.
30  *
31  *
32  * \file    slice_segment.c
33  *
34  * \brief   SSlice segment routine (Single slice/multiple slice/fmo arrangement exclusive)
35  *
36  * \date    2/4/2009 Created
37  *
38  *************************************************************************************
39  */
40 #include <string.h>
41 #include "rc.h"
42 #include "svc_enc_frame.h"
43 
44 namespace WelsEnc {
45 /*!
46  * \brief   Assign MB map for single slice segment
47  *
48  * \param   pMbMap          overall MB map
49  * \param   iCountMbNum     count number of MB
50  *
51  * \return  0 - successful; none 0 - failed
52  */
AssignMbMapSingleSlice(void * pMbMap,const int32_t kiCountMbNum,const int32_t kiMapUnitSize)53 int32_t AssignMbMapSingleSlice (void* pMbMap, const int32_t kiCountMbNum, const int32_t kiMapUnitSize) {
54   if (NULL == pMbMap || kiCountMbNum <= 0)
55     return 1;
56 
57   memset (pMbMap, 0, kiCountMbNum * kiMapUnitSize);
58 
59   return 0;
60 }
61 
62 /*!
63  * \brief   Assign MB map for multiple slice(s) segment
64  *
65  * \param   pCurDq              current layer which its MB map will be assigned
66  * \param   kpSliceArgument     slice argument for current layer
67  *
68  * \return  0 - successful; none 0 - failed
69  */
AssignMbMapMultipleSlices(SDqLayer * pCurDq,const SSliceArgument * kpSliceArgument)70 int32_t AssignMbMapMultipleSlices (SDqLayer* pCurDq, const SSliceArgument* kpSliceArgument) {
71   SSliceCtx* pSliceSeg   = &pCurDq->sSliceEncCtx;
72   int32_t iSliceIdx      = 0;
73   if (NULL == pSliceSeg || SM_SINGLE_SLICE == pSliceSeg->uiSliceMode)
74     return 1;
75 
76   if ((SM_RASTER_SLICE == pSliceSeg->uiSliceMode) && (0 == kpSliceArgument->uiSliceMbNum[0])) {
77     const int32_t kiMbWidth = pSliceSeg->iMbWidth;
78     int32_t iSliceNum = pSliceSeg->iSliceNumInFrame;
79 
80     iSliceIdx = 0;
81     while (iSliceIdx < iSliceNum) {
82       const int32_t kiFirstMb                       = iSliceIdx * kiMbWidth;
83       WelsSetMemMultiplebytes_c (pSliceSeg->pOverallMbMap + kiFirstMb, iSliceIdx,
84                                  kiMbWidth, sizeof (uint16_t));
85       ++ iSliceIdx;
86     }
87 
88     return 0;
89   } else if (SM_RASTER_SLICE  == pSliceSeg->uiSliceMode ||
90              SM_FIXEDSLCNUM_SLICE == pSliceSeg->uiSliceMode) {
91     const int32_t* kpSlicesAssignList           = (int32_t*) & (kpSliceArgument->uiSliceMbNum[0]);
92     const int32_t kiCountNumMbInFrame           = pSliceSeg->iMbNumInFrame;
93     const int32_t kiCountSliceNumInFrame        = pSliceSeg->iSliceNumInFrame;
94     int32_t iMbIdx                              = 0;
95 
96     iSliceIdx = 0;
97     do {
98       const int32_t kiCurRunLength                  = kpSlicesAssignList[iSliceIdx];
99       int32_t iRunIdx                               = 0;
100 
101       // due here need check validate mb_assign_map for input pData, can not use memset
102       do {
103         pSliceSeg->pOverallMbMap[iMbIdx + iRunIdx] = iSliceIdx;
104         ++ iRunIdx;
105       } while (iRunIdx < kiCurRunLength && iMbIdx + iRunIdx < kiCountNumMbInFrame);
106 
107       iMbIdx += kiCurRunLength;
108       ++ iSliceIdx;
109     } while (iSliceIdx < kiCountSliceNumInFrame && iMbIdx < kiCountNumMbInFrame);
110   } else if (SM_SIZELIMITED_SLICE == pSliceSeg->uiSliceMode) {
111     // do nothing,pSliceSeg->pOverallMbMap will be initial later
112   } else { // any else uiSliceMode?
113     assert (0);
114   }
115 
116   // extention for other multiple slice type in the future
117   return 1;
118 }
119 
120 /*!
121  *  Check slices assignment settings on MST_INTERLEAVE type
122  */
123 
124 //slice parameter check for SM_FIXEDSLCNUM_SLICE
CheckFixedSliceNumMultiSliceSetting(const int32_t kiMbNumInFrame,SSliceArgument * pSliceArg)125 bool CheckFixedSliceNumMultiSliceSetting (const int32_t kiMbNumInFrame, SSliceArgument* pSliceArg) {
126   int32_t* pSlicesAssignList    = (int32_t*) & (pSliceArg->uiSliceMbNum[0]);
127   const uint32_t kuiSliceNum    = pSliceArg->uiSliceNum;
128   uint32_t uiSliceIdx           = 0;
129   const int32_t kiMbNumPerSlice = kiMbNumInFrame / kuiSliceNum;
130   int32_t iNumMbLeft            = kiMbNumInFrame;
131 
132   if (NULL == pSlicesAssignList)
133     return false;
134 
135   for (; uiSliceIdx + 1 < kuiSliceNum; ++ uiSliceIdx) {
136     pSlicesAssignList[uiSliceIdx] = kiMbNumPerSlice;
137     iNumMbLeft -= kiMbNumPerSlice;
138   }
139 
140   pSlicesAssignList[uiSliceIdx] = iNumMbLeft;
141 
142   if (iNumMbLeft <= 0 || kiMbNumPerSlice <= 0) {
143     return false;
144   }
145 
146   return true;
147 }
148 
149 //slice parameter check for SM_ROWMB_SLICE
CheckRowMbMultiSliceSetting(const int32_t kiMbWidth,SSliceArgument * pSliceArg)150 bool CheckRowMbMultiSliceSetting (const int32_t kiMbWidth, SSliceArgument* pSliceArg) {
151   int32_t* pSlicesAssignList = (int32_t*) & (pSliceArg->uiSliceMbNum[0]);
152   const uint32_t kuiSliceNum            = pSliceArg->uiSliceNum;
153   uint32_t uiSliceIdx                   = 0;
154 
155   if (NULL == pSlicesAssignList)
156     return false;
157 
158   while (uiSliceIdx < kuiSliceNum) {
159     pSlicesAssignList[uiSliceIdx] = kiMbWidth;
160     ++ uiSliceIdx;
161   }
162   return true;
163 }
164 
165 //slice parameter check for SM_RASTER_SLICE
CheckRasterMultiSliceSetting(const int32_t kiMbNumInFrame,SSliceArgument * pSliceArg)166 bool CheckRasterMultiSliceSetting (const int32_t kiMbNumInFrame, SSliceArgument* pSliceArg) {
167   int32_t*      pSlicesAssignList = (int32_t*) & (pSliceArg->uiSliceMbNum[0]);
168   int32_t       iActualSliceCount       = 0;
169 
170   //check mb_num setting
171   uint32_t uiSliceIdx   = 0;
172   int32_t iCountMb      = 0;
173 
174   if (NULL == pSlicesAssignList)
175     return false;
176 
177   while ((uiSliceIdx < MAX_SLICES_NUM) && (0 < pSlicesAssignList[uiSliceIdx])) {
178     iCountMb            += pSlicesAssignList[uiSliceIdx];
179     iActualSliceCount   =  uiSliceIdx + 1;
180 
181     if (iCountMb >= kiMbNumInFrame) {
182       break;
183     }
184 
185     ++ uiSliceIdx;
186   }
187   //break condition above makes, after the while
188   // here must have (iActualSliceCount <= MAX_SLICES_NUM)
189 
190   //correction if needed
191   if (iCountMb == kiMbNumInFrame) {
192     ;
193   } else if (iCountMb > kiMbNumInFrame) {
194     //need correction:
195     //setting is more than iMbNumInFrame,
196     //cut the last uiSliceMbNum; adjust iCountMb
197     pSlicesAssignList[iActualSliceCount - 1] -= (iCountMb - kiMbNumInFrame);
198     iCountMb = kiMbNumInFrame;
199   } else if (iActualSliceCount < MAX_SLICES_NUM) {
200     //where ( iCountMb < iMbNumInFrame )
201     //can do correction:
202     //  make the last uiSliceMbNum the left num
203     pSlicesAssignList[iActualSliceCount] = kiMbNumInFrame - iCountMb;
204     iActualSliceCount += 1;
205   } else {
206     //here ( iCountMb < iMbNumInFrame ) && ( iActualSliceCount == MAX_SLICES_NUM )
207     //no more slice can be added
208     return false;
209   }
210 
211   pSliceArg->uiSliceNum = iActualSliceCount;
212   return true;
213 
214 }
215 
216 
217 // GOM based RC related for uiSliceNum decision, only used at SM_FIXEDSLCNUM_SLICE
GomValidCheckSliceNum(const int32_t kiMbWidth,const int32_t kiMbHeight,uint32_t * pSliceNum)218 bool GomValidCheckSliceNum (const int32_t kiMbWidth, const int32_t kiMbHeight, uint32_t* pSliceNum) {
219   const int32_t kiCountNumMb    = kiMbWidth * kiMbHeight;
220   uint32_t iSliceNum            = *pSliceNum;
221   int32_t iGomSize;
222 
223   //The default RC is Bit-rate mode[Yi], but need consider as below:
224   // Tuned to use max of mode0 and mode1 due can not refresh on this from rc mode changed outside, 8/16/2011
225   // NOTE: GOM_ROW_MODE0_?P is integer multipler of GOM_ROW_MODE1_?P, which predefined at rc.h there, so GOM_ROM take MODE0 as the initial
226   if (kiMbWidth <= MB_WIDTH_THRESHOLD_90P)
227     iGomSize = kiMbWidth * GOM_ROW_MODE0_90P;
228   else if (kiMbWidth <= MB_WIDTH_THRESHOLD_180P)
229     iGomSize = kiMbWidth *  GOM_ROW_MODE0_180P;
230   else if (kiMbWidth <= MB_WIDTH_THRESHOLD_360P)
231     iGomSize = kiMbWidth * GOM_ROW_MODE0_360P;
232   else
233     iGomSize = kiMbWidth * GOM_ROW_MODE0_720P;
234 
235   while (true) {
236     if (kiCountNumMb < iGomSize * (int32_t) iSliceNum) {
237       -- iSliceNum;
238       iSliceNum = iSliceNum - (iSliceNum & 0x01); // verfiy even num for multiple slices case
239       if (iSliceNum < 2) // for safe
240         break;
241       continue;
242     }
243     break;
244   }
245 
246   if (*pSliceNum != iSliceNum) {
247     *pSliceNum = (0 != iSliceNum) ? iSliceNum : 1;
248     return false;
249   }
250   return true;
251 }
252 
253 
254 // GOM based RC related for uiSliceMbNum decision, only used at SM_FIXEDSLCNUM_SLICE
GomValidCheckSliceMbNum(const int32_t kiMbWidth,const int32_t kiMbHeight,SSliceArgument * pSliceArg)255 bool GomValidCheckSliceMbNum (const int32_t kiMbWidth, const int32_t kiMbHeight, SSliceArgument* pSliceArg) {
256   uint32_t* pSlicesAssignList   = & (pSliceArg->uiSliceMbNum[0]);
257   const uint32_t kuiSliceNum    = pSliceArg->uiSliceNum;
258   const int32_t kiMbNumInFrame  = kiMbWidth * kiMbHeight;
259   const int32_t kiMbNumPerSlice = kiMbNumInFrame / kuiSliceNum;
260   int32_t iNumMbLeft            = kiMbNumInFrame;
261 
262   int32_t iMinimalMbNum         = kiMbWidth;    // in theory we need only 1 SMB, here let it as one SMB row required
263   int32_t iMaximalMbNum         = 0;    // dynamically assign later
264   int32_t iGomSize;
265 
266   uint32_t uiSliceIdx = 0; // for test
267 
268   // The default RC is Bit-rate mode [Yi], but need consider as below:
269   // Tuned to use max of mode0 and mode1 due can not refresh on this from rc mode changed outside, 8/16/2011
270   // NOTE: GOM_ROW_MODE0_?P is integer multipler of GOM_ROW_MODE1_?P, which predefined at rc.h there, so GOM_ROM take MODE0 as the initial
271   if (kiMbWidth <= MB_WIDTH_THRESHOLD_90P)
272     iGomSize = kiMbWidth * GOM_ROW_MODE0_90P;
273   else if (kiMbWidth <= MB_WIDTH_THRESHOLD_180P)
274     iGomSize = kiMbWidth * GOM_ROW_MODE0_180P;
275   else if (kiMbWidth <= MB_WIDTH_THRESHOLD_360P)
276     iGomSize = kiMbWidth * GOM_ROW_MODE0_360P;
277   else
278     iGomSize = kiMbWidth * GOM_ROW_MODE0_720P;
279   // GOM boundary aligned
280   int32_t iNumMbAssigning = WELS_DIV_ROUND (INT_MULTIPLY * kiMbNumPerSlice, iGomSize * INT_MULTIPLY) * iGomSize;
281   int32_t iCurNumMbAssigning = 0;
282 
283   iMinimalMbNum = iGomSize;
284   while (uiSliceIdx + 1 < kuiSliceNum) {
285     iMaximalMbNum = iNumMbLeft - (kuiSliceNum - uiSliceIdx - 1) * iMinimalMbNum; // get maximal num_mb in left parts
286     // make sure one GOM at least in each slice for safe
287     if (iNumMbAssigning < iMinimalMbNum)
288       iCurNumMbAssigning = iMinimalMbNum;
289     else if (iNumMbAssigning > iMaximalMbNum)
290       iCurNumMbAssigning = (iMaximalMbNum / iGomSize) * iGomSize;
291     else
292       iCurNumMbAssigning = iNumMbAssigning;
293 
294     if (iCurNumMbAssigning <= 0) {
295       return false;
296     }
297 
298     iNumMbLeft -= iCurNumMbAssigning;
299     if (iNumMbLeft <= 0)  {
300       return false;
301     }
302 
303     pSlicesAssignList[uiSliceIdx] = iCurNumMbAssigning;
304     ++ uiSliceIdx;
305   }
306   pSlicesAssignList[uiSliceIdx] = iNumMbLeft;
307   if (iNumMbLeft < iMinimalMbNum) {
308     return false;
309   }
310 
311   return true;
312 }
313 
314 
315 /*!
316  *  Get slice count for multiple slice segment
317  *
318  */
GetInitialSliceNum(SSliceArgument * pSliceArgument)319 int32_t GetInitialSliceNum (SSliceArgument* pSliceArgument) {
320   if (NULL == pSliceArgument)
321     return -1;
322 
323   switch (pSliceArgument->uiSliceMode) {
324   case SM_SINGLE_SLICE:
325   case SM_FIXEDSLCNUM_SLICE:
326   case SM_RASTER_SLICE: {
327     return pSliceArgument->uiSliceNum;
328   }
329   case SM_SIZELIMITED_SLICE: {
330     return AVERSLICENUM_CONSTRAINT;//at the beginning of dynamic slicing, set the uiSliceNum to be 1
331   }
332   case SM_RESERVED:
333   default: {
334     return -1;
335   }
336   }
337 
338   return -1;
339 }
340 
341 /*!
342  * \brief   Initialize slice segment (Single/multiple slices)
343  *
344  * \param   pCurDq              current layer which its SSlice segment will be initialized
345  * \param   uiSliceMode         SSlice mode
346  * \param   multi_slice_argv    Multiple slices argument
347  * \param   iMbWidth            MB width
348  * \param   iMbHeight           MB height
349  *
350  * \return  0 - successful; none 0 - failed;
351  */
InitSliceSegment(SDqLayer * pCurDq,CMemoryAlign * pMa,SSliceArgument * pSliceArgument,const int32_t kiMbWidth,const int32_t kiMbHeight)352 int32_t InitSliceSegment (SDqLayer* pCurDq,
353                           CMemoryAlign* pMa,
354                           SSliceArgument* pSliceArgument,
355                           const int32_t kiMbWidth,
356                           const int32_t kiMbHeight) {
357   SSliceCtx* pSliceSeg        = &pCurDq->sSliceEncCtx;
358   const int32_t kiCountMbNum  = kiMbWidth * kiMbHeight;
359   SliceModeEnum uiSliceMode   = SM_SINGLE_SLICE;
360 
361   if (NULL == pSliceSeg || NULL == pSliceArgument || kiMbWidth == 0 || kiMbHeight == 0)
362     return 1;
363 
364   uiSliceMode = pSliceArgument->uiSliceMode;
365   if (pSliceSeg->iMbNumInFrame == kiCountMbNum && pSliceSeg->iMbWidth == kiMbWidth
366       && pSliceSeg->iMbHeight == kiMbHeight && pSliceSeg->uiSliceMode == uiSliceMode && pSliceSeg->pOverallMbMap != NULL)
367     return 0;
368   else if (pSliceSeg->iMbNumInFrame != kiCountMbNum) {
369     if (NULL != pSliceSeg->pOverallMbMap) {
370       pMa->WelsFree (pSliceSeg->pOverallMbMap, "pSliceSeg->pOverallMbMap");
371 
372       pSliceSeg->pOverallMbMap = NULL;
373     }
374 
375     // just for safe
376     pSliceSeg->iSliceNumInFrame = 0;
377     pSliceSeg->iMbNumInFrame    = 0;
378     pSliceSeg->iMbWidth         = 0;
379     pSliceSeg->iMbHeight        = 0;
380     pSliceSeg->uiSliceMode      = SM_SINGLE_SLICE;      // sigle in default
381   }
382 
383   if (SM_SINGLE_SLICE == uiSliceMode) {
384     pSliceSeg->pOverallMbMap = (uint16_t*)pMa->WelsMallocz (kiCountMbNum * sizeof (uint16_t), "pSliceSeg->pOverallMbMap");
385 
386     WELS_VERIFY_RETURN_IF (1, NULL == pSliceSeg->pOverallMbMap)
387     pSliceSeg->iSliceNumInFrame = 1;
388 
389     pSliceSeg->uiSliceMode              = uiSliceMode;
390     pSliceSeg->iMbWidth                 = kiMbWidth;
391     pSliceSeg->iMbHeight                = kiMbHeight;
392     pSliceSeg->iMbNumInFrame            = kiCountMbNum;
393 
394     return AssignMbMapSingleSlice (pSliceSeg->pOverallMbMap, kiCountMbNum, sizeof (pSliceSeg->pOverallMbMap[0]));
395   } else { //if ( SM_MULTIPLE_SLICE == uiSliceMode )
396     if (uiSliceMode != SM_FIXEDSLCNUM_SLICE && uiSliceMode != SM_RASTER_SLICE
397         && uiSliceMode != SM_SIZELIMITED_SLICE)
398       return 1;
399 
400     pSliceSeg->pOverallMbMap = (uint16_t*)pMa->WelsMallocz (kiCountMbNum * sizeof (uint16_t), "pSliceSeg->pOverallMbMap");
401     WELS_VERIFY_RETURN_IF (1, NULL == pSliceSeg->pOverallMbMap)
402 
403     WelsSetMemMultiplebytes_c (pSliceSeg->pOverallMbMap, 0, kiCountMbNum, sizeof (uint16_t));
404 
405     //SM_SIZELIMITED_SLICE: init, set pSliceSeg->iSliceNumInFrame = 1;
406     pSliceSeg->iSliceNumInFrame = GetInitialSliceNum (pSliceArgument);
407     if (-1 == pSliceSeg->iSliceNumInFrame)
408       return 1;
409 
410     pSliceSeg->uiSliceMode      = pSliceArgument->uiSliceMode;
411 
412     pSliceSeg->iMbWidth         = kiMbWidth;
413     pSliceSeg->iMbHeight        = kiMbHeight;
414     pSliceSeg->iMbNumInFrame    = kiCountMbNum;
415     if (SM_SIZELIMITED_SLICE == pSliceArgument->uiSliceMode) {
416       if (0 < pSliceArgument->uiSliceSizeConstraint) {
417         pSliceSeg->uiSliceSizeConstraint = pSliceArgument->uiSliceSizeConstraint;
418       } else {
419         return 1;
420       }
421     } else {
422       pSliceSeg->uiSliceSizeConstraint = DEFAULT_MAXPACKETSIZE_CONSTRAINT;
423     }
424     // about "iMaxSliceNumConstraint"
425     //only used in SM_SIZELIMITED_SLICE mode so far,
426     //now follows NAL_UNIT_CONSTRAINT, (see definition)
427     //will be adjusted under MT if there is limitation on iLayerNum
428     pSliceSeg->iMaxSliceNumConstraint = MAX_SLICES_NUM;
429 
430 
431     return AssignMbMapMultipleSlices (pCurDq, pSliceArgument);
432   }
433   return 0;
434 }
435 
436 /*!
437  * \brief   Uninitialize slice segment (Single/multiple slices)
438  *
439  * \param   pCurDq           current layer which its SSlice segment will be uninitialized
440  *
441  * \return  none;
442  */
UninitSliceSegment(SDqLayer * pCurDq,CMemoryAlign * pMa)443 void UninitSliceSegment (SDqLayer* pCurDq, CMemoryAlign* pMa) {
444   SSliceCtx* pSliceSeg = &pCurDq->sSliceEncCtx;
445   if (NULL != pSliceSeg) {
446     if (NULL != pSliceSeg->pOverallMbMap) {
447       pMa->WelsFree (pSliceSeg->pOverallMbMap, "pSliceSeg->pOverallMbMap");
448 
449       pSliceSeg->pOverallMbMap = NULL;
450     }
451 
452     pSliceSeg->uiSliceMode      = SM_SINGLE_SLICE;      // single in default
453     pSliceSeg->iMbWidth         = 0;
454     pSliceSeg->iMbHeight        = 0;
455     pSliceSeg->iSliceNumInFrame = 0;
456     pSliceSeg->iMbNumInFrame    = 0;
457     pSliceSeg->uiSliceSizeConstraint   = 0;
458     pSliceSeg->iMaxSliceNumConstraint  = 0;
459   }
460 }
461 
462 
463 /*!
464  * \brief   Initialize Wels SSlice context (Single/multiple slices and FMO)
465  *
466  * \param   pCurDq          current layer which its SSlice context will be initialized
467  * \param   bFmoUseFlag     flag of using fmo
468  * \param   iMbWidth        MB width
469  * \param   iMbHeight       MB height
470  * \param   uiSliceMode     slice mode
471  * \param   mul_slice_arg   argument for multiple slice if it is applicable
472  * \param   pPpsArg         argument for pPps parameter
473  *
474  * \return  0 - successful; none 0 - failed;
475  */
InitSlicePEncCtx(SDqLayer * pCurDq,CMemoryAlign * pMa,bool bFmoUseFlag,int32_t iMbWidth,int32_t iMbHeight,SSliceArgument * pSliceArgument,void * pPpsArg)476 int32_t InitSlicePEncCtx (SDqLayer* pCurDq,
477                           CMemoryAlign* pMa,
478                           bool bFmoUseFlag,
479                           int32_t iMbWidth,
480                           int32_t iMbHeight,
481                           SSliceArgument* pSliceArgument,
482                           void* pPpsArg) {
483   if (NULL == pCurDq)
484     return 1;
485 
486   InitSliceSegment (pCurDq,
487                     pMa,
488                     pSliceArgument,
489                     iMbWidth,
490                     iMbHeight);
491   return 0;
492 }
493 
494 
495 /*!
496  * \brief   Uninitialize Wels SSlice context (Single/multiple slices and FMO)
497  *
498  * \param   pCurDq       current layer which its SSlice context will be initialized
499  *
500  * \return  NONE;
501  */
UninitSlicePEncCtx(SDqLayer * pCurDq,CMemoryAlign * pMa)502 void UninitSlicePEncCtx (SDqLayer* pCurDq, CMemoryAlign* pMa) {
503   if (NULL != pCurDq) {
504     UninitSliceSegment (pCurDq, pMa);
505   }
506 }
507 
508 /*!
509  * \brief   Get slice idc for given iMbXY (apply in Single/multiple slices and FMO)
510  *
511  * \param   pCurDq    current layer info
512  * \param   kiMbXY    MB xy index
513  *
514  * \return  uiSliceIdc - successful; -1 - failed;
515  */
WelsMbToSliceIdc(SDqLayer * pCurDq,const int32_t kiMbXY)516 uint16_t WelsMbToSliceIdc (SDqLayer* pCurDq, const int32_t kiMbXY) {
517   if (NULL == pCurDq)
518     return (uint16_t) (-1);
519 
520   SSliceCtx* pSliceCtx = &pCurDq->sSliceEncCtx;
521   if (NULL != pSliceCtx && kiMbXY < pSliceCtx->iMbNumInFrame && kiMbXY >= 0)
522     return pSliceCtx->pOverallMbMap[ kiMbXY ];
523   return (uint16_t) (-1);
524 }
525 
526 /*!
527  * \brief   Get first mb in slice/slice_group: uiSliceIdc (apply in Single/multiple slices and FMO)
528  *
529  * \param   pCurLayer       current layer
530  * \param   kuiSliceIdc     slice idc
531  *
532  * \return  iFirstMb - successful; -1 - failed;
533  */
WelsGetFirstMbOfSlice(SDqLayer * pCurLayer,const int32_t kuiSliceIdc)534 int32_t WelsGetFirstMbOfSlice (SDqLayer* pCurLayer, const int32_t kuiSliceIdc) {
535   if (NULL == pCurLayer || NULL == pCurLayer->pFirstMbIdxOfSlice) {
536     return -1;
537   }
538 
539   return pCurLayer->pFirstMbIdxOfSlice[kuiSliceIdc];
540 }
541 
542 /*!
543  * \brief   Get successive mb to be processed in slice/slice_group: uiSliceIdc (apply in Single/multiple slices and FMO)
544  *
545  * \param   pCurDq     current layer info
546  * \param   kiMbXY     MB xy index
547  *
548  * \return  next_mb - successful; -1 - failed;
549  */
WelsGetNextMbOfSlice(SDqLayer * pCurDq,const int32_t kiMbXY)550 int32_t WelsGetNextMbOfSlice (SDqLayer* pCurDq, const int32_t kiMbXY) {
551   if (NULL != pCurDq) {
552     SSliceCtx* pSliceSeg = &pCurDq->sSliceEncCtx;
553     if (NULL == pSliceSeg || kiMbXY < 0 || kiMbXY >= pSliceSeg->iMbNumInFrame)
554       return -1;
555     if (SM_SINGLE_SLICE == pSliceSeg->uiSliceMode) {
556       int32_t iNextMbIdx = kiMbXY;
557       ++ iNextMbIdx;
558       if (iNextMbIdx >= pSliceSeg->iMbNumInFrame)
559         iNextMbIdx = -1;
560       return iNextMbIdx;
561     } else { /*if ( SM_MULTIPLE_SLICE == pSliceSeg->uiSliceMode )*/
562       if (SM_RESERVED != pSliceSeg->uiSliceMode) {
563         int32_t iNextMbIdx = kiMbXY;
564         ++ iNextMbIdx;
565         if (iNextMbIdx < pSliceSeg->iMbNumInFrame && pSliceSeg->pOverallMbMap != NULL
566             && pSliceSeg->pOverallMbMap[iNextMbIdx] == pSliceSeg->pOverallMbMap[ kiMbXY ])
567           return iNextMbIdx;
568         return -1;
569       } else
570         return -1; // reserved here for other multiple slice type
571     }
572   } else
573     return -1;
574 }
575 
576 /*!
577  * \brief   Get previous mb to be processed in slice/slice_group: uiSliceIdc (apply in Single/multiple slices and FMO)
578  *
579  * \param   pCurDq     current layer info
580  * \param   kiMbXY     MB xy index
581  *
582  * \return  prev_mb - successful; -1 - failed;
583  */
WelsGetPrevMbOfSlice(SDqLayer * pCurDq,const int32_t kiMbXY)584 int32_t WelsGetPrevMbOfSlice (SDqLayer* pCurDq, const int32_t kiMbXY) {
585   if (NULL != pCurDq) {
586     SSliceCtx* pSliceSeg = &pCurDq->sSliceEncCtx;
587     if (NULL == pSliceSeg || kiMbXY < 0 || kiMbXY >= pSliceSeg->iMbNumInFrame)
588       return -1;
589     if (pSliceSeg->uiSliceMode == SM_SINGLE_SLICE)
590       return (-1 + kiMbXY);
591     else { /* if ( pSliceSeg->uiSliceMode == SM_MULTIPLE_SLICE )*/
592       if (SM_RESERVED == pSliceSeg->uiSliceMode) {
593         int32_t iPrevMbIdx = kiMbXY;
594         -- iPrevMbIdx;
595         if (iPrevMbIdx >= 0 && iPrevMbIdx < pSliceSeg->iMbNumInFrame && NULL != pSliceSeg->pOverallMbMap
596             && pSliceSeg->pOverallMbMap[ kiMbXY ] == pSliceSeg->pOverallMbMap[ iPrevMbIdx ])
597           return iPrevMbIdx;
598         return -1;
599       } else
600         return -1;
601     }
602   } else
603     return -1;
604 }
605 
606 /*!
607  * \brief   Get number of mb in slice/slice_group: uiSliceIdc (apply in Single/multiple slices and FMO)
608  *
609  * \param   pSliceCtx       SSlice context
610  * \param   pSlice          slice which request slice num
611  * \param   kuiSliceIdc     slice/slice_group idc
612  *
613  * \return  count_num_of_mb - successful; -1 - failed;
614  */
WelsGetNumMbInSlice(SDqLayer * pCurDq,SSlice * pSlice,const int32_t kuiSliceIdc)615 int32_t WelsGetNumMbInSlice (SDqLayer* pCurDq, SSlice* pSlice, const int32_t kuiSliceIdc) {
616   SSliceCtx* pSliceCtx = &pCurDq->sSliceEncCtx;
617   bool bInValidFlag    = false;
618 
619   if (NULL == pSliceCtx || NULL == pSlice || kuiSliceIdc < 0) {
620     return -1;
621   }
622 
623   bInValidFlag = ((SM_SINGLE_SLICE != pSliceCtx->uiSliceMode) && (kuiSliceIdc >= pSliceCtx->iSliceNumInFrame))
624                  || ((SM_SINGLE_SLICE == pSliceCtx->uiSliceMode) && (kuiSliceIdc > 0));
625   if (bInValidFlag) {
626     return -1;
627   }
628 
629   return pSlice->iCountMbNumInSlice;
630 }
631 
GetCurrentSliceNum(const SDqLayer * pCurDq)632 int32_t GetCurrentSliceNum (const SDqLayer* pCurDq) {
633   const SSliceCtx* kpSliceCtx = &pCurDq->sSliceEncCtx;
634   return (kpSliceCtx != NULL) ? (kpSliceCtx->iSliceNumInFrame) : (-1);
635 }
DynamicAdjustSlicePEncCtxAll(SDqLayer * pCurDq,int32_t * pRunLength)636 int32_t DynamicAdjustSlicePEncCtxAll (SDqLayer* pCurDq,
637                                       int32_t* pRunLength) {
638   SSliceCtx* pSliceCtx                  = &pCurDq->sSliceEncCtx;
639   const int32_t iCountNumMbInFrame      = pSliceCtx->iMbNumInFrame;
640   const int32_t iCountSliceNumInFrame   = pSliceCtx->iSliceNumInFrame;
641   int32_t iSameRunLenFlag               = 1;
642   int32_t iFirstMbIdx                   = 0;
643   int32_t iSliceIdx                     = 0;
644 
645   assert (iCountSliceNumInFrame <= MAX_THREADS_NUM);
646 
647   while (iSliceIdx < iCountSliceNumInFrame) {
648     if (pRunLength[iSliceIdx] != pCurDq->pFirstMbIdxOfSlice[iSliceIdx]) {
649       iSameRunLenFlag = 0;
650       break;
651     }
652     ++ iSliceIdx;
653   }
654   if (iSameRunLenFlag) {
655     return 1; // do not need adjust it due to same running length as before to save complexity
656   }
657 
658   iSliceIdx = 0;
659   do {
660     const int32_t kiSliceRun = pRunLength[iSliceIdx];
661     pCurDq->pFirstMbIdxOfSlice[iSliceIdx]         = iFirstMbIdx;
662     pCurDq->pCountMbNumInSlice[iSliceIdx]         = kiSliceRun;
663 
664     WelsSetMemMultiplebytes_c (pSliceCtx->pOverallMbMap + iFirstMbIdx, iSliceIdx,
665                                kiSliceRun, sizeof (uint16_t));
666 
667     iFirstMbIdx += kiSliceRun;
668 
669     ++ iSliceIdx;
670   } while (iSliceIdx < iCountSliceNumInFrame && iFirstMbIdx < iCountNumMbInFrame);
671 
672   return 0;
673 }
674 
DynamicMaxSliceNumConstraint(uint32_t uiMaximumNum,int32_t iConsumedNum,uint32_t iDulplicateTimes)675 int32_t DynamicMaxSliceNumConstraint (uint32_t uiMaximumNum, int32_t iConsumedNum, uint32_t iDulplicateTimes) {
676   return ((uiMaximumNum - iConsumedNum - 1) / iDulplicateTimes);
677 }
678 
679 } // namespace WelsEnc
680