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