Showing the changes to codec/decoder/core/src/fmo.cpp (1 of 308 files). Show all
Unified · Split
| @@ -0,0 +1,355 @@ | |||
| 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 fmo.c | ||
| 33 | * | ||
| 34 | * \brief Flexible Macroblock Ordering implementation | ||
| 35 | * | ||
| 36 | * \date 2/4/2009 Created | ||
| 37 | * | ||
| 38 | ************************************************************************************* | ||
| 39 | */ | ||
| 40 | #include <string.h> | ||
| 41 | |||
| 42 | #include "fmo.h" | ||
| 43 | #include "macros.h" | ||
| 44 | #include "utils.h" | ||
| 45 | #include "mem_align.h" | ||
| 46 | |||
| 47 | namespace WelsDec { | ||
| 48 | |||
| 49 | /*! | ||
| 50 | * \brief Generate MB allocated map for interleaved slice group (TYPE 0) | ||
| 51 | * | ||
| 52 | * \param pFmo fmo context | ||
| 53 | * \param pPps pps context | ||
| 54 | * | ||
| 55 | * \return 0 - successful; none 0 - failed | ||
| 56 | */ | ||
| 57 | static inline int32_t FmoGenerateMbAllocMapType0( PFmo pFmo, PPps pPps ) | ||
| 58 | { | ||
| 59 | uint32_t uiNumSliceGroups = 0; | ||
| 60 | int32_t iMbNum = 0; | ||
| 61 | int32_t i = 0; | ||
| 62 | |||
| 63 | WELS_VERIFY_RETURN_IF( 1, ( NULL == pFmo || NULL == pPps ) ) | ||
| 64 | uiNumSliceGroups = pPps->uiNumSliceGroups; | ||
| 65 | iMbNum = pFmo->iCountMbNum; | ||
| 66 | WELS_VERIFY_RETURN_IF( 1, ( NULL == pFmo->pMbAllocMap || iMbNum <= 0 || uiNumSliceGroups >= MAX_SLICEGROUP_IDS ) ) | ||
| 67 | |||
| 68 | do | ||
| 69 | { | ||
| 70 | uint8_t uiGroup = 0; | ||
| 71 | do { | ||
| 72 | const int32_t kiRunIdx = pPps->uiRunLength[uiGroup]; | ||
| 73 | int32_t j = 0; | ||
| 74 | do { | ||
| 75 | pFmo->pMbAllocMap[i+j] = uiGroup; | ||
| 76 | ++ j; | ||
| 77 | } while(j < kiRunIdx && i + j < iMbNum); | ||
| 78 | i += kiRunIdx; | ||
| 79 | ++ uiGroup; | ||
| 80 | } while(uiGroup < uiNumSliceGroups && i < iMbNum); | ||
| 81 | }while(i < iMbNum); | ||
| 82 | |||
| 83 | return 0; // well here | ||
| 84 | } | ||
| 85 | |||
| 86 | /*! | ||
| 87 | * \brief Generate MB allocated map for dispersed slice group (TYPE 1) | ||
| 88 | * | ||
| 89 | * \param pFmo fmo context | ||
| 90 | * \param pPps pps context | ||
| 91 | * \param iMbWidth MB width | ||
| 92 | * | ||
| 93 | * \return 0 - successful; none 0 - failed | ||
| 94 | */ | ||
| 95 | static inline int32_t FmoGenerateMbAllocMapType1( PFmo pFmo, PPps pPps, const int32_t kiMbWidth ) | ||
| 96 | { | ||
| 97 | uint32_t uiNumSliceGroups = 0; | ||
| 98 | int32_t iMbNum = 0; | ||
| 99 | int16_t i = 0; | ||
| 100 | WELS_VERIFY_RETURN_IF( 1, ( NULL == pFmo || NULL == pPps ) ) | ||
| 101 | uiNumSliceGroups = pPps->uiNumSliceGroups; | ||
| 102 | iMbNum = pFmo->iCountMbNum; | ||
| 103 | WELS_VERIFY_RETURN_IF( 1, ( NULL == pFmo->pMbAllocMap || iMbNum <= 0 || kiMbWidth == 0 || uiNumSliceGroups >= MAX_SLICEGROUP_IDS ) ) | ||
| 104 | |||
| 105 | do | ||
| 106 | { | ||
| 107 | pFmo->pMbAllocMap[i] = (uint8_t)(((i % kiMbWidth)+(((i / kiMbWidth)*uiNumSliceGroups)>>1)) % uiNumSliceGroups); | ||
| 108 | ++ i; | ||
| 109 | }while (i < iMbNum); | ||
| 110 | |||
| 111 | return 0; // well here | ||
| 112 | } | ||
| 113 | |||
| 114 | /*! | ||
| 115 | * \brief Generate MB allocated map for various type of slice group cases (TYPE 0, .., 6) | ||
| 116 | * | ||
| 117 | * \param pFmo fmo context | ||
| 118 | * \param pPps pps context | ||
| 119 | * \param kiMbWidth MB width | ||
| 120 | * \param kiMbHeight MB height | ||
| 121 | * | ||
| 122 | * \return 0 - successful; none 0 - failed | ||
| 123 | */ | ||
| 124 | static inline int32_t FmoGenerateSliceGroup( PFmo pFmo, const PPps kpPps, const int32_t kiMbWidth, const int32_t kiMbHeight ) | ||
| 125 | { | ||
| 126 | int32_t iNumMb = 0; | ||
| 127 | int32_t iErr = 0; | ||
| 128 | bool_t bResolutionChanged = false; | ||
| 129 | |||
| 130 | // the cases we would not like | ||
| 131 | WELS_VERIFY_RETURN_IF( 1, ( NULL == pFmo || NULL == kpPps ) ) | ||
| 132 | |||
| 133 | iNumMb = pFmo->iCountMbNum; | ||
| 134 | |||
| 135 | iNumMb = kiMbWidth * kiMbHeight; | ||
| 136 | |||
| 137 | if ( 0 == iNumMb ) | ||
| 138 | return 1; | ||
| 139 | |||
| 140 | |||
| 141 | WelsFree(pFmo->pMbAllocMap, "_fmo->pMbAllocMap"); | ||
| 142 | pFmo->pMbAllocMap = (uint8_t *)WelsMalloc( iNumMb * sizeof(uint8_t), "_fmo->pMbAllocMap" ); | ||
| 143 | WELS_VERIFY_RETURN_IF( 1, (NULL == pFmo->pMbAllocMap) ) // out of memory | ||
| 144 | |||
| 145 | pFmo->iCountMbNum = iNumMb; | ||
| 146 | |||
| 147 | if ( kpPps->uiNumSliceGroups < 2 && iNumMb > 0) // only one slice group, exactly it is single slice based | ||
| 148 | { | ||
| 149 | memset ( pFmo->pMbAllocMap, 0, iNumMb * sizeof(int8_t)); // for safe | ||
| 150 | |||
| 151 | pFmo->iSliceGroupCount = 1; | ||
| 152 | |||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | if ( bResolutionChanged || ((int32_t)kpPps->uiSliceGroupMapType != pFmo->iSliceGroupType) | ||
| 157 | || ((int32_t)kpPps->uiNumSliceGroups != pFmo->iSliceGroupCount) ) | ||
| 158 | { | ||
| 159 | switch ( kpPps->uiSliceGroupMapType ) | ||
| 160 | { | ||
| 161 | case 0: | ||
| 162 | iErr = FmoGenerateMbAllocMapType0( pFmo, kpPps ); | ||
| 163 | break; | ||
| 164 | case 1: | ||
| 165 | iErr = FmoGenerateMbAllocMapType1( pFmo, kpPps, kiMbWidth ); | ||
| 166 | break; | ||
| 167 | case 2: | ||
| 168 | case 3: | ||
| 169 | case 4: | ||
| 170 | case 5: | ||
| 171 | case 6: | ||
| 172 | // Reserve for others slice group type | ||
| 173 | iErr = 1; | ||
| 174 | break; | ||
| 175 | default: | ||
| 176 | return 1; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | if ( 0 == iErr ) // well now | ||
| 181 | { | ||
| 182 | pFmo->iSliceGroupCount = kpPps->uiNumSliceGroups; | ||
| 183 | pFmo->iSliceGroupType = kpPps->uiSliceGroupMapType; | ||
| 184 | } | ||
| 185 | |||
| 186 | return iErr; | ||
| 187 | } | ||
| 188 | |||
| 189 | /*! | ||
| 190 | * \brief Initialize Wels Flexible Macroblock Ordering (FMO) | ||
| 191 | * | ||
| 192 | * \param pFmo Wels fmo to be initialized | ||
| 193 | * \param pPps pps argument | ||
| 194 | * \param kiMbWidth mb width | ||
| 195 | * \param kiMbHeight mb height | ||
| 196 | * | ||
| 197 | * \return 0 - successful; none 0 - failed; | ||
| 198 | */ | ||
| 199 | int32_t InitFmo( PFmo pFmo, PPps pPps, const int32_t kiMbWidth, const int32_t kiMbHeight ) | ||
| 200 | { | ||
| 201 | return FmoGenerateSliceGroup( pFmo, pPps, kiMbWidth, kiMbHeight ); | ||
| 202 | } | ||
| 203 | |||
| 204 | |||
| 205 | /*! | ||
| 206 | * \brief Uninitialize Wels Flexible Macroblock Ordering (FMO) list | ||
| 207 | * | ||
| 208 | * \param pFmo Wels base fmo ptr to be uninitialized | ||
| 209 | * \param kiCnt count number of PPS per list | ||
| 210 | * \param kiAvail count available number of PPS in list | ||
| 211 | * | ||
| 212 | * \return NONE | ||
| 213 | */ | ||
| 214 | void_t UninitFmoList( PFmo pFmo, const int32_t kiCnt, const int32_t kiAvail ) | ||
| 215 | { | ||
| 216 | PFmo pIter = pFmo; | ||
| 217 | int32_t i = 0; | ||
| 218 | int32_t iFreeNodes = 0; | ||
| 219 | |||
| 220 | if ( NULL == pIter || kiAvail <= 0 || kiCnt < kiAvail ) | ||
| 221 | return; | ||
| 222 | |||
| 223 | while ( i < kiCnt ) { | ||
| 224 | if ( pIter != NULL && pIter->bActiveFlag ) | ||
| 225 | { | ||
| 226 | if ( NULL != pIter->pMbAllocMap ) | ||
| 227 | { | ||
| 228 | WelsFree( pIter->pMbAllocMap, "pIter->pMbAllocMap" ); | ||
| 229 | |||
| 230 | pIter->pMbAllocMap = NULL; | ||
| 231 | } | ||
| 232 | pIter->iSliceGroupCount = 0; | ||
| 233 | pIter->iSliceGroupType = -1; | ||
| 234 | pIter->iCountMbNum = 0; | ||
| 235 | pIter->bActiveFlag = false; | ||
| 236 | ++ iFreeNodes; | ||
| 237 | if ( iFreeNodes >= kiAvail ) | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | ++ pIter; | ||
| 241 | ++ i; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | /*! | ||
| 246 | * \brief detect parameter sets are changed or not | ||
| 247 | * | ||
| 248 | * \param pFmo fmo context | ||
| 249 | * \param kiCountNumMb (iMbWidth * iMbHeight) in Sps | ||
| 250 | * \param iSliceGroupType slice group type if fmo is exactly enabled | ||
| 251 | * \param iSliceGroupCount slice group count if fmo is exactly enabled | ||
| 252 | * | ||
| 253 | * \return true - changed or not initialized yet; false - not change at all | ||
| 254 | */ | ||
| 255 | bool_t FmoParamSetsChanged( PFmo pFmo, const int32_t kiCountNumMb, const int32_t kiSliceGroupType, const int32_t kiSliceGroupCount ) | ||
| 256 | { | ||
| 257 | WELS_VERIFY_RETURN_IF( false, (NULL == pFmo) ) | ||
| 258 | |||
| 259 | return ( (!pFmo->bActiveFlag) | ||
| 260 | || (kiCountNumMb != pFmo->iCountMbNum) | ||
| 261 | || (kiSliceGroupType != pFmo->iSliceGroupType) | ||
| 262 | || (kiSliceGroupCount != pFmo->iSliceGroupCount) ); | ||
| 263 | } | ||
| 264 | |||
| 265 | /*! | ||
| 266 | * \brief update/insert FMO parameter unit | ||
| 267 | * | ||
| 268 | * \param _fmo FMO context | ||
| 269 | * \param _sps PSps | ||
| 270 | * \param _pps PPps | ||
| 271 | * \param pActiveFmoNum int32_t* [in/out] | ||
| 272 | * | ||
| 273 | * \return true - update/insert successfully; false - failed; | ||
| 274 | */ | ||
| 275 | bool_t FmoParamUpdate( PFmo pFmo, PSps pSps, PPps pPps, int32_t *pActiveFmoNum ) | ||
| 276 | { | ||
| 277 | const uint32_t kuiMbWidth = pSps->iMbWidth; | ||
| 278 | const uint32_t kuiMbHeight= pSps->iMbHeight; | ||
| 279 | |||
| 280 | if ( FmoParamSetsChanged( pFmo, | ||
| 281 | kuiMbWidth * kuiMbHeight, | ||
| 282 | pPps->uiSliceGroupMapType, | ||
| 283 | pPps->uiNumSliceGroups ) ) | ||
| 284 | { | ||
| 285 | |||
| 286 | if ( InitFmo( pFmo, pPps, kuiMbWidth, kuiMbHeight ) ) | ||
| 287 | { | ||
| 288 | return false; | ||
| 289 | } | ||
| 290 | else | ||
| 291 | { | ||
| 292 | if ( !pFmo->bActiveFlag && *pActiveFmoNum < MAX_PPS_COUNT ) | ||
| 293 | { | ||
| 294 | ++ (*pActiveFmoNum); | ||
| 295 | pFmo->bActiveFlag = true; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | return true; | ||
| 301 | } | ||
| 302 | |||
| 303 | /*! | ||
| 304 | * \brief Convert kMbXy to slice group idc correspondingly | ||
| 305 | * | ||
| 306 | * \param pFmo Wels fmo context | ||
| 307 | * \param kMbXy kMbXy to be converted | ||
| 308 | * | ||
| 309 | * \return slice group idc - successful; -1 - failed; | ||
| 310 | */ | ||
| 311 | int32_t FmoMbToSliceGroup( PFmo pFmo, const MB_XY_T kiMbXy ) | ||
| 312 | { | ||
| 313 | const int32_t kiMbNum = pFmo->iCountMbNum; | ||
| 314 | const uint8_t* kpMbMap = pFmo->pMbAllocMap; | ||
| 315 | |||
| 316 | if ( kiMbXy < 0 || kiMbXy >= kiMbNum || kpMbMap == NULL) | ||
| 317 | return -1; | ||
| 318 | |||
| 319 | return kpMbMap[ kiMbXy ]; | ||
| 320 | } | ||
| 321 | |||
| 322 | /*! | ||
| 323 | * \brief Get successive mb to be processed with given current kMbXy | ||
| 324 | * | ||
| 325 | * \param pFmo Wels fmo context | ||
| 326 | * \param kMbXy current kMbXy | ||
| 327 | * | ||
| 328 | * \return iNextMb - successful; -1 - failed; | ||
| 329 | */ | ||
| 330 | MB_XY_T FmoNextMb( PFmo pFmo, const MB_XY_T kiMbXy ) | ||
| 331 | { | ||
| 332 | const int32_t kiTotalMb = pFmo->iCountMbNum; | ||
| 333 | const uint8_t* kpMbMap = pFmo->pMbAllocMap; | ||
| 334 | MB_XY_T iNextMb = kiMbXy; | ||
| 335 | const uint8_t kuiSliceGroupIdc = (uint8_t)FmoMbToSliceGroup( pFmo, kiMbXy ); | ||
| 336 | |||
| 337 | if (kuiSliceGroupIdc == (uint8_t)(-1)) | ||
| 338 | return -1; | ||
| 339 | |||
| 340 | do { | ||
| 341 | ++ iNextMb; | ||
| 342 | if (iNextMb >= kiTotalMb){ | ||
| 343 | iNextMb = -1; | ||
| 344 | break; | ||
| 345 | } | ||
| 346 | if (kpMbMap[iNextMb] == kuiSliceGroupIdc){ | ||
| 347 | break; | ||
| 348 | } | ||
| 349 | } while( 1 ); | ||
| 350 | |||
| 351 | // -1: No further MB in this slice (could be end of picture) | ||
| 352 | return iNextMb; | ||
| 353 | } | ||
| 354 | |||
| 355 | } // namespace WelsDec | ||