Showing the changes to codec/encoder/core/src/encoder_ext.cpp (1 of 225 files). Show all
Unified · Split
| @@ -1,4250 +1,4032 @@ | ||
| 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 encoder_ext.c | |
| 33 | − * | |
| 34 | − * \brief core encoder for SVC | |
| 35 | − * | |
| 36 | − * \date 7/24/2009 Created | |
| 37 | − * | |
| 38 | − ************************************************************************************* | |
| 39 | − */ | |
| 40 | −#include <string.h> | |
| 41 | −#include <stdlib.h> | |
| 42 | −#include <assert.h> | |
| 43 | − | |
| 44 | −#include "encoder.h" | |
| 45 | −#include "extern.h" | |
| 46 | −#include "encoder_context.h" | |
| 47 | −#include "typedefs.h" | |
| 48 | −#include "wels_const.h" | |
| 49 | −#include "wels_common_basis.h" | |
| 50 | −#include "codec_def.h" | |
| 51 | −#include "param_svc.h" | |
| 52 | −#include "cpu_core.h" | |
| 53 | −#include "cpu.h" | |
| 54 | −#include "utils.h" | |
| 55 | −#include "svc_enc_frame.h" | |
| 56 | −#include "svc_enc_golomb.h" | |
| 57 | −#include "svc_enc_slice_segment.h" | |
| 58 | −#include "au_set.h" | |
| 59 | −#include "picture_handle.h" | |
| 60 | −#include "codec_app_def.h" | |
| 61 | −#include "svc_base_layer_md.h" | |
| 62 | −#include "svc_encode_slice.h" | |
| 63 | −#include "decode_mb_aux.h" | |
| 64 | −#include "deblocking.h" | |
| 65 | −#include "rc.h" | |
| 66 | −#include "ref_list_mgr_svc.h" | |
| 67 | −#include "md.h" | |
| 68 | −#include "ls_defines.h" | |
| 69 | −#include "set_mb_syn_cavlc.h" | |
| 70 | −#include "crt_util_safe_x.h" // Safe CRT routines like utils for cross platforms | |
| 71 | −#include "array_stack_align.h" | |
| 72 | −// for MT, 4/22/2010 | |
| 73 | −#include "slice_multi_threading.h" | |
| 74 | −#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 75 | −#include "measure_time.h" | |
| 76 | −#endif//DYNAMIC_SLICE_ASSIGN | |
| 77 | − | |
| 78 | −namespace WelsSVCEnc { | |
| 79 | − | |
| 80 | − | |
| 81 | −int32_t WelsCodeOnePicPartition( sWelsEncCtx *pCtx, | |
| 82 | − SLayerBSInfo *pLbi, | |
| 83 | − int32_t *pNalIdxInLayer, | |
| 84 | − int32_t* pLayerSize, | |
| 85 | − int32_t iFirstMbInPartition, // first mb inclusive in partition | |
| 86 | − int32_t iEndMbInPartition, // end mb exclusive in partition | |
| 87 | − int32_t iStartSliceIdx | |
| 88 | − ); | |
| 89 | − | |
| 90 | − | |
| 91 | −/*! | |
| 92 | − * \brief validate checking in parameter configuration | |
| 93 | − * \pParam pParam SWelsSvcCodingParam* | |
| 94 | − * \return successful - 0; otherwise none 0 for failed | |
| 95 | − */ | |
| 96 | −int32_t ParamValidation( SWelsSvcCodingParam *pCfg ) | |
| 97 | −{ | |
| 98 | − float fMaxFrameRate = 0.0f; | |
| 99 | − const float fEpsn = 0.000001f; | |
| 100 | − int32_t i = 0; | |
| 101 | − int32_t iLastSpatialWidth = 0; | |
| 102 | − int32_t iLastSpatialHeight = 0; | |
| 103 | − float fLastFrameRateIn = 0.0f; | |
| 104 | − float fLastFrameRateOut = 0.0f; | |
| 105 | − SDLayerParam *pLastSpatialParam = NULL; | |
| 106 | − | |
| 107 | − assert( pCfg != NULL ); | |
| 108 | − | |
| 109 | − for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) | |
| 110 | − { | |
| 111 | − SDLayerParam *fDlp = &pCfg->sDependencyLayers[i]; | |
| 112 | − if ( fDlp->fOutputFrameRate > fDlp->fInputFrameRate || (fDlp->fInputFrameRate >= -fEpsn && fDlp->fInputFrameRate <= fEpsn) | |
| 113 | − || (fDlp->fOutputFrameRate >= -fEpsn && fDlp->fOutputFrameRate <= fEpsn) ) | |
| 114 | − { | |
| 115 | −#if defined (_DEBUG) | |
| 116 | − fprintf(stderr, "Invalid settings in input frame rate(%.6f) or output frame rate(%.6f) of layer #%d config file..\n", | |
| 117 | − fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i); | |
| 118 | −#endif | |
| 119 | − return 1; | |
| 120 | − } | |
| 121 | − if ( UINT_MAX == GetLogFactor(fDlp->fOutputFrameRate, fDlp->fInputFrameRate) ) | |
| 122 | − { | |
| 123 | −#if defined (_DEBUG) | |
| 124 | − fprintf(stderr, "Invalid settings in input frame rate(%.6f) and output frame rate(%.6f) of layer #%d config file: iResult of output frame rate divided by input frame rate should be power of 2(i.e,in/pOut=2^n)..\n", | |
| 125 | − fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i); | |
| 126 | −#endif | |
| 127 | − return 1; | |
| 128 | − } | |
| 129 | − } | |
| 130 | − | |
| 131 | − for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) | |
| 132 | − { | |
| 133 | − SDLayerParam *fDlp = &pCfg->sDependencyLayers[i]; | |
| 134 | − if ( fDlp->fInputFrameRate > fMaxFrameRate ) | |
| 135 | − fMaxFrameRate = fDlp->fInputFrameRate; | |
| 136 | − } | |
| 137 | − | |
| 138 | − if ( fMaxFrameRate > fEpsn && (fMaxFrameRate - pCfg->fMaxFrameRate > fEpsn || fMaxFrameRate - pCfg->fMaxFrameRate < -fEpsn) ) | |
| 139 | − { | |
| 140 | − pCfg->fMaxFrameRate = fMaxFrameRate; | |
| 141 | − } | |
| 142 | − | |
| 143 | − for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) | |
| 144 | − { | |
| 145 | − SDLayerParam *fDlp = &pCfg->sDependencyLayers[i]; | |
| 146 | − | |
| 147 | − pLastSpatialParam = fDlp; | |
| 148 | − iLastSpatialWidth = fDlp->iFrameWidth; | |
| 149 | − iLastSpatialHeight = fDlp->iFrameHeight; | |
| 150 | − fLastFrameRateIn = fDlp->fInputFrameRate; | |
| 151 | − fLastFrameRateOut = fDlp->fOutputFrameRate; | |
| 152 | − } | |
| 153 | − | |
| 154 | − return 0; | |
| 155 | −} | |
| 156 | − | |
| 157 | −int32_t ParamValidationExt( void *pParam ) | |
| 158 | −{ | |
| 159 | − SWelsSvcCodingParam *pCodingParam = (SWelsSvcCodingParam *)pParam; | |
| 160 | − int8_t i = 0; | |
| 161 | − int32_t iIdx = 0; | |
| 162 | − | |
| 163 | − assert ( pCodingParam != NULL ); | |
| 164 | − if ( NULL == pCodingParam ) | |
| 165 | − return 1; | |
| 166 | − | |
| 167 | − if ( pCodingParam->iNumDependencyLayer < 1 || pCodingParam->iNumDependencyLayer > MAX_DEPENDENCY_LAYER ){ | |
| 168 | −#if defined (_DEBUG) | |
| 169 | − fprintf(stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumDependencyLayer: %d!\n", pCodingParam->iNumDependencyLayer); | |
| 170 | −#endif//#if _DEBUG | |
| 171 | − | |
| 172 | − return 1; | |
| 173 | − } | |
| 174 | − | |
| 175 | − if ( pCodingParam->iNumTemporalLayer < 1 || pCodingParam->iNumTemporalLayer > MAX_TEMPORAL_LEVEL ){ | |
| 176 | −#if defined (_DEBUG) | |
| 177 | − fprintf(stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumTemporalLayer: %d!\n", pCodingParam->iNumTemporalLayer); | |
| 178 | −#endif//#if _DEBUG | |
| 179 | − return 1; | |
| 180 | − } | |
| 181 | − | |
| 182 | − if ( pCodingParam->uiGopSize < 1 || pCodingParam->uiGopSize > MAX_GOP_SIZE ){ | |
| 183 | −#if defined (_DEBUG) | |
| 184 | − fprintf(stderr, "ParamValidationExt(), monitor invalid pCodingParam->uiGopSize: %d!\n", pCodingParam->uiGopSize); | |
| 185 | −#endif//#if _DEBUG | |
| 186 | − return 1; | |
| 187 | − } | |
| 188 | − | |
| 189 | − | |
| 190 | − if ( pCodingParam->uiIntraPeriod && pCodingParam->uiIntraPeriod < pCodingParam->uiGopSize ) | |
| 191 | − { | |
| 192 | −#if defined (_DEBUG) | |
| 193 | − fprintf(stderr, "ParamValidationExt(), uiIntraPeriod(%d) should be not less than that of uiGopSize(%d) or -1 specified!\n", | |
| 194 | − pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize); | |
| 195 | −#endif//#if _DEBUG | |
| 196 | − return 1; | |
| 197 | − } | |
| 198 | − | |
| 199 | − if ( pCodingParam->uiIntraPeriod && (pCodingParam->uiIntraPeriod & (pCodingParam->uiGopSize-1)) != 0 ) | |
| 200 | − { | |
| 201 | −#if defined (_DEBUG) | |
| 202 | − fprintf(stderr, "ParamValidationExt(), uiIntraPeriod(%d) should be multiple of uiGopSize(%d) or -1 specified!\n", | |
| 203 | − pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize); | |
| 204 | −#endif//#if _DEBUG | |
| 205 | − return 1; | |
| 206 | − } | |
| 207 | − | |
| 208 | − | |
| 209 | −#ifdef MT_ENABLED | |
| 210 | − //about iMultipleThreadIdc, bDeblockingParallelFlag, iLoopFilterDisableIdc, & uiSliceMode | |
| 211 | − // (1) Single Thread | |
| 212 | − // if (THREAD==1)//single thread | |
| 213 | − // no parallel_deblocking: bDeblockingParallelFlag = 0; | |
| 214 | − // (2) Multi Thread: see uiSliceMode decision | |
| 215 | − if ( pCodingParam->iMultipleThreadIdc == 1 ) | |
| 216 | − { | |
| 217 | − //now is single thread. no parallel deblocking, set flag=0 | |
| 218 | − pCodingParam->bDeblockingParallelFlag = false; | |
| 219 | − } | |
| 220 | − else | |
| 221 | − { | |
| 222 | − pCodingParam->bDeblockingParallelFlag = true; | |
| 223 | − } | |
| 224 | −#else | |
| 225 | − pCodingParam->bDeblockingParallelFlag = false; | |
| 226 | −#endif//MT_ENABLED | |
| 227 | − | |
| 228 | − for ( i = 0; i < pCodingParam->iNumDependencyLayer; ++ i ){ | |
| 229 | − SDLayerParam *fDlp = &pCodingParam->sDependencyLayers[i]; | |
| 230 | − const int32_t kiPicWidth = fDlp->iFrameWidth; | |
| 231 | − const int32_t kiPicHeight= fDlp->iFrameHeight; | |
| 232 | − int32_t iMbWidth = 0; | |
| 233 | − int32_t iMbHeight = 0; | |
| 234 | − int32_t iMbNumInFrame = 0; | |
| 235 | − int32_t iMaxSliceNum = MAX_SLICES_NUM; | |
| 236 | − if ( kiPicWidth <= 0 || kiPicHeight <= 0 ){ | |
| 237 | −#if defined (_DEBUG) | |
| 238 | − fprintf(stderr, "ParamValidationExt(), invalid %d x %d in dependency layer settings!\n", kiPicWidth, kiPicHeight); | |
| 239 | −#endif//#if _DEBUG | |
| 240 | − return 1; | |
| 241 | − } | |
| 242 | − if ( (kiPicWidth & 0x0F) != 0 || (kiPicHeight & 0x0F) != 0 ){ | |
| 243 | −#if defined (_DEBUG) | |
| 244 | − fprintf(stderr, "ParamValidationExt(), in layer #%d iWidth x iHeight(%d x %d) both should be multiple of 16, can not support with arbitrary size currently!\n", i, kiPicWidth, kiPicHeight); | |
| 245 | −#endif//#if _DEBUG | |
| 246 | − return 1; | |
| 247 | − } | |
| 248 | − | |
| 249 | − if ( fDlp->sMso.uiSliceMode >= SM_RESERVED ){ | |
| 250 | −#if defined (_DEBUG) | |
| 251 | − fprintf(stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", fDlp->sMso.uiSliceMode ); | |
| 252 | −#endif//#if _DEBUG | |
| 253 | − return 1; | |
| 254 | − } | |
| 255 | − | |
| 256 | − //check pSlice settings under multi-pSlice | |
| 257 | − if ( kiPicWidth<=16 && kiPicHeight<=16 ){ | |
| 258 | − //only have one MB, set to single_slice | |
| 259 | − fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 260 | − } | |
| 261 | − switch ( fDlp->sMso.uiSliceMode ) | |
| 262 | − { | |
| 263 | − case SM_SINGLE_SLICE: | |
| 264 | − fDlp->sMso.sSliceArgument.iSliceNum = 1; | |
| 265 | − fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | |
| 266 | − fDlp->sMso.sSliceArgument.iSliceNum = 0; | |
| 267 | − for (iIdx=0; iIdx<MAX_SLICES_NUM;iIdx++) | |
| 268 | − { | |
| 269 | − fDlp->sMso.sSliceArgument.uiSliceMbNum[iIdx] = 0; | |
| 270 | − } | |
| 271 | − break; | |
| 272 | − case SM_FIXEDSLCNUM_SLICE: | |
| 273 | − { | |
| 274 | − fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | |
| 275 | − | |
| 276 | − iMbWidth = (kiPicWidth+15)>>4; | |
| 277 | − iMbHeight = (kiPicHeight+15)>>4; | |
| 278 | − iMbNumInFrame = iMbWidth * iMbHeight; | |
| 279 | − iMaxSliceNum = MAX_SLICES_NUM; | |
| 280 | − if ( fDlp->sMso.sSliceArgument.iSliceNum <= 0 | |
| 281 | − || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum ) | |
| 282 | − { | |
| 283 | −#if defined (_DEBUG) | |
| 284 | − fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum ); | |
| 285 | −#endif//#if _DEBUG | |
| 286 | − return 1; | |
| 287 | − } | |
| 288 | − if (fDlp->sMso.sSliceArgument.iSliceNum == 1) | |
| 289 | − { | |
| 290 | −#if defined (_DEBUG) | |
| 291 | − fprintf(stderr, "ParamValidationExt(), uiSliceNum(%d) you set for SM_FIXEDSLCNUM_SLICE, now turn to SM_SINGLE_SLICE type!\n", fDlp->sMso.sSliceArgument.iSliceNum ); | |
| 292 | −#endif//#if _DEBUG | |
| 293 | − fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 294 | − break; | |
| 295 | − } | |
| 296 | − if (pCodingParam->bEnableRc) // multiple slices verify with gom | |
| 297 | − { | |
| 298 | − //check uiSliceNum | |
| 299 | − GomValidCheckSliceNum( iMbWidth, iMbHeight, (int32_t*)&fDlp->sMso.sSliceArgument.iSliceNum ); | |
| 300 | − assert(fDlp->sMso.sSliceArgument.iSliceNum > 1); | |
| 301 | − //set uiSliceMbNum with current uiSliceNum | |
| 302 | − GomValidCheckSliceMbNum( iMbWidth, iMbHeight, &fDlp->sMso.sSliceArgument ); | |
| 303 | − } | |
| 304 | − else if ( !CheckFixedSliceNumMultiSliceSetting( iMbNumInFrame, &fDlp->sMso.sSliceArgument ) ) // verify interleave mode settings | |
| 305 | − {//check uiSliceMbNum with current uiSliceNum | |
| 306 | −#if defined (_DEBUG) | |
| 307 | − fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] ); | |
| 308 | −#endif//#if _DEBUG | |
| 309 | − return 1; | |
| 310 | − } | |
| 311 | − // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting | |
| 312 | − if ( iMbNumInFrame <= MIN_NUM_MB_PER_SLICE ) | |
| 313 | − { | |
| 314 | − fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 315 | − fDlp->sMso.sSliceArgument.iSliceNum = 1; | |
| 316 | − break; | |
| 317 | − } | |
| 318 | − } | |
| 319 | − break; | |
| 320 | − case SM_RASTER_SLICE: | |
| 321 | − { | |
| 322 | − fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | |
| 323 | − | |
| 324 | − iMbWidth = (kiPicWidth+15)>>4; | |
| 325 | − iMbHeight = (kiPicHeight+15)>>4; | |
| 326 | − iMbNumInFrame = iMbWidth * iMbHeight; | |
| 327 | − iMaxSliceNum = MAX_SLICES_NUM; | |
| 328 | − if ( fDlp->sMso.sSliceArgument.uiSliceMbNum[0] <= 0 ) | |
| 329 | − { | |
| 330 | −#if defined (_DEBUG) | |
| 331 | − fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] ); | |
| 332 | −#endif//#if _DEBUG | |
| 333 | − return 1; | |
| 334 | − } | |
| 335 | − | |
| 336 | − if ( !CheckRasterMultiSliceSetting( iMbNumInFrame, &fDlp->sMso.sSliceArgument ) ) // verify interleave mode settings | |
| 337 | − { | |
| 338 | −#if defined (_DEBUG) | |
| 339 | − fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] ); | |
| 340 | −#endif//#if _DEBUG | |
| 341 | − return 1; | |
| 342 | − } | |
| 343 | − if ( fDlp->sMso.sSliceArgument.iSliceNum <= 0 || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum ) // verify interleave mode settings | |
| 344 | − { | |
| 345 | −#if defined (_DEBUG) | |
| 346 | − fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) in SM_RASTER_SLICE settings!\n", fDlp->sMso.sSliceArgument.iSliceNum ); | |
| 347 | −#endif//#if _DEBUG | |
| 348 | − return 1; | |
| 349 | − } | |
| 350 | − if (fDlp->sMso.sSliceArgument.iSliceNum == 1) | |
| 351 | − { | |
| 352 | −#if defined (_DEBUG) | |
| 353 | − fprintf(stderr, "ParamValidationExt(), pSlice setting for SM_RASTER_SLICE now turn to SM_SINGLE_SLICE!\n" ); | |
| 354 | −#endif//#if _DEBUG | |
| 355 | − fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 356 | − break; | |
| 357 | − } | |
| 358 | −#ifdef MT_ENABLED | |
| 359 | − if (pCodingParam->bEnableRc && fDlp->sMso.sSliceArgument.iSliceNum > 1) | |
| 360 | − { | |
| 361 | −#if defined (_DEBUG) | |
| 362 | − fprintf(stderr, "ParamValidationExt(), WARNING: GOM based RC do not support SM_RASTER_SLICE!\n" ); | |
| 363 | −#endif//#if _DEBUG | |
| 364 | − } | |
| 365 | −#endif | |
| 366 | − // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting | |
| 367 | − if ( iMbNumInFrame <= MIN_NUM_MB_PER_SLICE ) | |
| 368 | − { | |
| 369 | − fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 370 | − fDlp->sMso.sSliceArgument.iSliceNum = 1; | |
| 371 | − break; | |
| 372 | − } | |
| 373 | − } | |
| 374 | − break; | |
| 375 | − case SM_ROWMB_SLICE: | |
| 376 | − { | |
| 377 | − fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | |
| 378 | − | |
| 379 | − iMbWidth = (kiPicWidth+15)>>4; | |
| 380 | − iMbHeight = (kiPicHeight+15)>>4; | |
| 381 | − iMaxSliceNum = MAX_SLICES_NUM; | |
| 382 | − if ( iMbHeight > iMaxSliceNum ) | |
| 383 | − { | |
| 384 | −#if defined (_DEBUG) | |
| 385 | − fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings more than MAX!\n", iMbHeight ); | |
| 386 | −#endif//#if _DEBUG | |
| 387 | − return 1; | |
| 388 | − } | |
| 389 | − fDlp->sMso.sSliceArgument.iSliceNum = iMbHeight; | |
| 390 | − | |
| 391 | − if ( fDlp->sMso.sSliceArgument.iSliceNum <= 0 ) | |
| 392 | − { | |
| 393 | −#if defined (_DEBUG) | |
| 394 | − fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum ); | |
| 395 | −#endif//#if _DEBUG | |
| 396 | − return 1; | |
| 397 | − } | |
| 398 | − if ( !CheckRowMbMultiSliceSetting( iMbWidth, &fDlp->sMso.sSliceArgument ) ) // verify interleave mode settings | |
| 399 | − { | |
| 400 | −#if defined (_DEBUG) | |
| 401 | − fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] ); | |
| 402 | −#endif//#if _DEBUG | |
| 403 | − return 1; | |
| 404 | − } | |
| 405 | − } | |
| 406 | − break; | |
| 407 | − case SM_DYN_SLICE: | |
| 408 | − { | |
| 409 | − iMbWidth = (kiPicWidth+15)>>4; | |
| 410 | − iMbHeight = (kiPicHeight+15)>>4; | |
| 411 | − if ( fDlp->sMso.sSliceArgument.uiSliceSizeConstraint <= 0 ) | |
| 412 | − { | |
| 413 | −#if defined (_DEBUG) | |
| 414 | − fprintf(stderr, "ParamValidationExt(), invalid iSliceSize (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceSizeConstraint ); | |
| 415 | −#endif//#if _DEBUG | |
| 416 | − return 1; | |
| 417 | − } | |
| 418 | − // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting | |
| 419 | − if ( iMbWidth * iMbHeight <= MIN_NUM_MB_PER_SLICE ) | |
| 420 | − { | |
| 421 | − fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 422 | − fDlp->sMso.sSliceArgument.iSliceNum = 1; | |
| 423 | − break; | |
| 424 | − } | |
| 425 | − } | |
| 426 | − break; | |
| 427 | − default: | |
| 428 | − { | |
| 429 | − | |
| 430 | −#if defined (_DEBUG) | |
| 431 | − fprintf(stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", pCodingParam->sDependencyLayers[0].sMso.uiSliceMode ); | |
| 432 | −#endif//#if _DEBUG | |
| 433 | − return 1; | |
| 434 | − | |
| 435 | − } | |
| 436 | − break; | |
| 437 | − } | |
| 438 | − } | |
| 439 | − | |
| 440 | − return ParamValidation(pCodingParam); | |
| 441 | −} | |
| 442 | − | |
| 443 | −/*! | |
| 444 | − * \brief acquire count number of layers and NALs based on configurable paramters dependency | |
| 445 | − * \pParam pCtx sWelsEncCtx* | |
| 446 | − * \pParam pParam SWelsSvcCodingParam* | |
| 447 | − * \pParam pCountLayers pointer of count number of layers indeed | |
| 448 | − * \pParam iCountNals pointer of count number of nals indeed | |
| 449 | − * \return 0 - successful; otherwise failed | |
| 450 | − */ | |
| 451 | −static inline int32_t AcquireLayersNals( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pParam, int32_t *pCountLayers, int32_t *pCountNals ) | |
| 452 | −{ | |
| 453 | − int32_t iCountNumLayers = 0; | |
| 454 | − int32_t iCountNumNals = 0; | |
| 455 | − int32_t iNumDependencyLayers = 0; | |
| 456 | − int32_t iDIndex = 0; | |
| 457 | −#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 458 | − int32_t iNumLayersPack = 0; | |
| 459 | −#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | |
| 460 | − | |
| 461 | − if ( NULL == pParam || NULL == ppCtx || NULL == *ppCtx ) | |
| 462 | − return 1; | |
| 463 | − | |
| 464 | − iNumDependencyLayers = pParam->iNumDependencyLayer; | |
| 465 | − | |
| 466 | − do { | |
| 467 | − SDLayerParam *pDLayer = &pParam->sDependencyLayers[iDIndex]; | |
| 468 | −// pDLayer->ptr_cfg = pParam; | |
| 469 | − int32_t iOrgNumNals = iCountNumNals; | |
| 470 | − | |
| 471 | − //Note: Sep. 2010 | |
| 472 | − //Review this part and suggest no change, since the memory over-use | |
| 473 | − //(1) counts little to the overall performance | |
| 474 | − //(2) should not be critial even under mobile case | |
| 475 | − if ( SM_DYN_SLICE == pDLayer->sMso.uiSliceMode ) | |
| 476 | − { | |
| 477 | − iCountNumNals += MAX_SLICES_NUM; | |
| 478 | − // plus prefix NALs | |
| 479 | − if ( iDIndex == 0 ) | |
| 480 | − iCountNumNals += MAX_SLICES_NUM; | |
| 481 | − // MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME ensured at svc_enc_slice_segment.h | |
| 482 | −#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 483 | − assert(MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME); | |
| 484 | − // iNumLayersPack += MAX_SLICES_NUM; // do not count it for dynamic slicing mode | |
| 485 | −#else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER | |
| 486 | − assert(iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER ); | |
| 487 | −#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | |
| 488 | − } | |
| 489 | − else /*if ( SM_SINGLE_SLICE != pDLayer->sMso.uiSliceMode )*/ | |
| 490 | − { | |
| 491 | − const int32_t kiNumOfSlice = GetInitialSliceNum( (pDLayer->iFrameWidth+0x0f)>>4, | |
| 492 | − (pDLayer->iFrameHeight+0x0f)>>4, | |
| 493 | − &pDLayer->sMso ); | |
| 494 | − | |
| 495 | − // NEED check iCountNals value in case multiple slices is used | |
| 496 | − iCountNumNals += kiNumOfSlice; // for pSlice VCL NALs | |
| 497 | − // plus prefix NALs | |
| 498 | − if ( iDIndex == 0 ) | |
| 499 | − iCountNumNals += kiNumOfSlice; | |
| 500 | −#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 501 | − assert(num_of_slice <= MAX_SLICES_NUM && MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME); | |
| 502 | − iNumLayersPack += num_of_slice; | |
| 503 | −#else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER | |
| 504 | − assert(iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER ); | |
| 505 | −#endif//MT_ENALBED && PACKING_ONE_SLICE_PER_LAYER | |
| 506 | − if ( kiNumOfSlice > MAX_SLICES_NUM ) | |
| 507 | − { | |
| 508 | − WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), num_of_slice(%d) > MAX_SLICES_NUM(%d) per (iDid= %d, qid= %d) settings!\n", | |
| 509 | − kiNumOfSlice, MAX_SLICES_NUM, iDIndex, 0 ); | |
| 510 | − return 1; | |
| 511 | − } | |
| 512 | − } | |
| 513 | −#if !defined(MT_ENABLED) || !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 514 | − if ( iCountNumNals - iOrgNumNals > MAX_NAL_UNITS_IN_LAYER ) | |
| 515 | − { | |
| 516 | − WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), num_of_nals(%d) > MAX_NAL_UNITS_IN_LAYER(%d) per (iDid= %d, qid= %d) settings!\n", | |
| 517 | − (iCountNumNals - iOrgNumNals), MAX_NAL_UNITS_IN_LAYER, iDIndex, 0 ); | |
| 518 | − return 1; | |
| 519 | − } | |
| 520 | −#endif//!MT_ENABLED) || !PACKING_ONE_SLICE_PER_LAYER | |
| 521 | − | |
| 522 | − iCountNumLayers ++; | |
| 523 | − | |
| 524 | − ++ iDIndex; | |
| 525 | − } while(iDIndex < iNumDependencyLayers); | |
| 526 | − | |
| 527 | − iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers<<1) + iCountNumLayers; // plus iCountNumLayers for reserved application | |
| 528 | −#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 529 | − iNumLayersPack += 1 + iNumDependencyLayers + (iCountNumLayers<<1); | |
| 530 | −#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | |
| 531 | − | |
| 532 | − // to check number of layers / nals / slices dependencies, 12/8/2010 | |
| 533 | −#if !defined(MT_ENABLED) | |
| 534 | − if ( iCountNumLayers > MAX_LAYER_NUM_OF_FRAME ) | |
| 535 | − { | |
| 536 | − WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", iCountNumLayers, MAX_LAYER_NUM_OF_FRAME ); | |
| 537 | − return 1; | |
| 538 | − } | |
| 539 | −#else//MT_ENABLED | |
| 540 | −#if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 541 | − if ( iNumLayersPack > MAX_LAYER_NUM_OF_FRAME ) | |
| 542 | − { | |
| 543 | − WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), num_layers_pack_overall(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", iNumLayersPack, MAX_LAYER_NUM_OF_FRAME ); | |
| 544 | − return 1; | |
| 545 | − } | |
| 546 | −#else//!PACKING_ONE_SLICE_PER_LAYER | |
| 547 | − if ( iCountNumLayers > MAX_LAYER_NUM_OF_FRAME ) | |
| 548 | − { | |
| 549 | − WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", iCountNumLayers, MAX_LAYER_NUM_OF_FRAME ); | |
| 550 | − return 1; | |
| 551 | − } | |
| 552 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 553 | −#endif//!MT_ENABLED | |
| 554 | − | |
| 555 | − if ( NULL != pCountLayers ) | |
| 556 | − *pCountLayers = iCountNumLayers; | |
| 557 | − if ( NULL != pCountNals ) | |
| 558 | − *pCountNals = iCountNumNals; | |
| 559 | − return 0; | |
| 560 | −} | |
| 561 | − | |
| 562 | −/*! | |
| 563 | − * \brief alloc spatial layers pictures (I420 based source pictures) | |
| 564 | − */ | |
| 565 | −int32_t AllocSpatialPictures( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pParam ) | |
| 566 | −{ | |
| 567 | − CMemoryAlign *pMa = (*ppCtx)->pMemAlign; | |
| 568 | − const int32_t kiDlayerCount = pParam->iNumDependencyLayer; | |
| 569 | − int32_t iDlayerIndex = 0; | |
| 570 | − | |
| 571 | − // spatial pictures | |
| 572 | − iDlayerIndex = 0; | |
| 573 | − do { | |
| 574 | − const int32_t kiPicWidth = pParam->sDependencyLayers[iDlayerIndex].iFrameWidth; | |
| 575 | − const int32_t kiPicHeight = pParam->sDependencyLayers[iDlayerIndex].iFrameHeight; | |
| 576 | − const uint8_t kuiLayerInTemporal = 2 + WELS_MAX(pParam->sDependencyLayers[iDlayerIndex].iHighestTemporalId, 1); | |
| 577 | − const uint8_t kuiRefNumInTemporal = kuiLayerInTemporal + pParam->iLTRRefNum; | |
| 578 | − uint8_t i = 0; | |
| 579 | − | |
| 580 | − do { | |
| 581 | − SPicture *pPic = AllocPicture( pMa, kiPicWidth, kiPicHeight, false ); | |
| 582 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pPic), FreeMemorySvc(ppCtx); *ppCtx = NULL ) | |
| 583 | − (*ppCtx)->pSpatialPic[iDlayerIndex][i] = pPic; | |
| 584 | − ++ i; | |
| 585 | − } while( i < kuiRefNumInTemporal); | |
| 586 | − | |
| 587 | − (*ppCtx)->uiSpatialLayersInTemporal[iDlayerIndex] = kuiLayerInTemporal; | |
| 588 | − (*ppCtx)->uiSpatialPicNum[iDlayerIndex] = kuiRefNumInTemporal; | |
| 589 | − ++ iDlayerIndex; | |
| 590 | − } while( iDlayerIndex < kiDlayerCount ); | |
| 591 | − | |
| 592 | − return 0; | |
| 593 | −} | |
| 594 | − | |
| 595 | −void FreeSpatialPictures( sWelsEncCtx *pCtx ) | |
| 596 | −{ | |
| 597 | − CMemoryAlign *pMa = pCtx->pMemAlign; | |
| 598 | − int32_t j = 0; | |
| 599 | − while( j < pCtx->pSvcParam->iNumDependencyLayer ) | |
| 600 | − { | |
| 601 | − uint8_t i = 0; | |
| 602 | − uint8_t uiRefNumInTemporal = pCtx->uiSpatialPicNum[j]; | |
| 603 | − | |
| 604 | − while( i < uiRefNumInTemporal ) | |
| 605 | − { | |
| 606 | − if ( NULL != pCtx->pSpatialPic[j][i] ) | |
| 607 | − { | |
| 608 | − FreePicture( pMa, &pCtx->pSpatialPic[j][i] ); | |
| 609 | − } | |
| 610 | − ++ i; | |
| 611 | − } | |
| 612 | − pCtx->uiSpatialLayersInTemporal[j] = 0; | |
| 613 | − ++ j; | |
| 614 | − } | |
| 615 | − | |
| 616 | −} | |
| 617 | − | |
| 618 | −static void InitMbInfo(sWelsEncCtx * pEnc, SMB * pList, SDqLayer * pLayer, const int32_t kiDlayerId, const int32_t kiMaxMbNum ) | |
| 619 | −{ | |
| 620 | − int32_t iMbWidth = pLayer->iMbWidth; | |
| 621 | − int32_t iMbHeight = pLayer->iMbHeight; | |
| 622 | − int32_t iIdx; | |
| 623 | − int32_t iMbNum = iMbWidth * iMbHeight; | |
| 624 | − SSliceCtx *pSliceCtx= pLayer->pSliceEncCtx; | |
| 625 | − uint32_t uiNeighborAvail; | |
| 626 | − const int32_t kiOffset = (kiDlayerId & 0x01) * kiMaxMbNum; | |
| 627 | − SMVUnitXY (*pLayerMvUnitBlock4x4)[MB_BLOCK4x4_NUM] = (SMVUnitXY(*)[MB_BLOCK4x4_NUM])(&pEnc->pMvUnitBlock4x4[MB_BLOCK4x4_NUM*kiOffset]); | |
| 628 | − int8_t (*pLayerRefIndexBlock8x8)[MB_BLOCK8x8_NUM] = (int8_t(*)[MB_BLOCK8x8_NUM])(&pEnc->pRefIndexBlock4x4[MB_BLOCK8x8_NUM*kiOffset]); | |
| 629 | − | |
| 630 | − for( iIdx = 0; iIdx<iMbNum; iIdx++ ){ | |
| 631 | − BOOL_T bLeft; | |
| 632 | − BOOL_T bTop; | |
| 633 | − BOOL_T bLeftTop; | |
| 634 | − BOOL_T bRightTop; | |
| 635 | − int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY; | |
| 636 | − uint8_t uiSliceIdc; | |
| 637 | − | |
| 638 | − pList[iIdx].iMbX = pEnc->pStrideTab->pMbIndexX[kiDlayerId][iIdx]; | |
| 639 | − pList[iIdx].iMbY = pEnc->pStrideTab->pMbIndexY[kiDlayerId][iIdx]; | |
| 640 | − pList[iIdx].iMbXY = iIdx; | |
| 641 | − | |
| 642 | − uiSliceIdc = WelsMbToSliceIdc(pSliceCtx, iIdx); | |
| 643 | − iLeftXY = iIdx - 1; | |
| 644 | − iTopXY = iIdx - iMbWidth; | |
| 645 | − iLeftTopXY = iTopXY - 1; | |
| 646 | − iRightTopXY = iTopXY + 1; | |
| 647 | − | |
| 648 | − bLeft = (pList[iIdx].iMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iLeftXY)); | |
| 649 | − bTop = (pList[iIdx].iMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iTopXY)); | |
| 650 | − bLeftTop = (pList[iIdx].iMbX > 0) && (pList[iIdx].iMbY > 0) && (uiSliceIdc == | |
| 651 | − WelsMbToSliceIdc(pSliceCtx, iLeftTopXY)); | |
| 652 | − bRightTop = (pList[iIdx].iMbX < (iMbWidth-1)) && (pList[iIdx].iMbY > 0) && (uiSliceIdc == | |
| 653 | − WelsMbToSliceIdc(pSliceCtx, iRightTopXY)); | |
| 654 | − | |
| 655 | − uiNeighborAvail = 0; | |
| 656 | − if( bLeft ){ | |
| 657 | − uiNeighborAvail |= LEFT_MB_POS; | |
| 658 | − } | |
| 659 | − if( bTop ){ | |
| 660 | − uiNeighborAvail |= TOP_MB_POS; | |
| 661 | − } | |
| 662 | − if( bLeftTop ){ | |
| 663 | − uiNeighborAvail |= TOPLEFT_MB_POS; | |
| 664 | − } | |
| 665 | − if( bRightTop ){ | |
| 666 | − uiNeighborAvail |= TOPRIGHT_MB_POS; | |
| 667 | − } | |
| 668 | − pList[iIdx].uiSliceIdc = uiSliceIdc; // merge from svc_hd_opt_b for multiple slices coding | |
| 669 | − pList[iIdx].uiNeighborAvail = uiNeighborAvail; | |
| 670 | − uiNeighborAvail = 0; | |
| 671 | − if(pList[iIdx].iMbX >= BASE_MV_MB_NMB) | |
| 672 | − uiNeighborAvail |= LEFT_MB_POS; | |
| 673 | − if(pList[iIdx].iMbX <= (iMbWidth-1-BASE_MV_MB_NMB)) | |
| 674 | − uiNeighborAvail |= RIGHT_MB_POS; | |
| 675 | − if (pList[iIdx].iMbY >= BASE_MV_MB_NMB) | |
| 676 | − uiNeighborAvail |= TOP_MB_POS; | |
| 677 | − if(pList[iIdx].iMbY <= (iMbHeight-1-BASE_MV_MB_NMB)) | |
| 678 | − uiNeighborAvail |= BOTTOM_MB_POS; | |
| 679 | − | |
| 680 | − pList[iIdx].sMv = pLayerMvUnitBlock4x4[iIdx]; | |
| 681 | − pList[iIdx].pRefIndex = pLayerRefIndexBlock8x8[iIdx]; | |
| 682 | − pList[iIdx].pSadCost = &pEnc->pSadCostMb[iIdx]; | |
| 683 | − pList[iIdx].pIntra4x4PredMode = &pEnc->pIntra4x4PredModeBlocks[iIdx*INTRA_4x4_MODE_NUM]; | |
| 684 | − pList[iIdx].pNonZeroCount = &pEnc->pNonZeroCountBlocks[iIdx*MB_LUMA_CHROMA_BLOCK4x4_NUM]; | |
| 685 | − } | |
| 686 | −} | |
| 687 | − | |
| 688 | − | |
| 689 | −int32_t InitMbListD( sWelsEncCtx ** ppCtx) | |
| 690 | −{ | |
| 691 | − int32_t iNumDlayer = (*ppCtx)->pSvcParam->iNumDependencyLayer; | |
| 692 | − int32_t iMbSize[MAX_DEPENDENCY_LAYER] = { 0 }; | |
| 693 | − int32_t iOverallMbNum = 0; | |
| 694 | − int32_t iMbWidth = 0; | |
| 695 | − int32_t iMbHeight= 0; | |
| 696 | − int32_t i; | |
| 697 | − | |
| 698 | − if ( iNumDlayer > MAX_DEPENDENCY_LAYER ) | |
| 699 | − return 1; | |
| 700 | − | |
| 701 | − for( i=0;i<iNumDlayer;i++ ){ | |
| 702 | − iMbWidth = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameWidth + 15)>>4; | |
| 703 | − iMbHeight = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameHeight + 15)>>4; | |
| 704 | − iMbSize[i] = iMbWidth * iMbHeight; | |
| 705 | − iOverallMbNum += iMbSize[i]; | |
| 706 | − } | |
| 707 | − | |
| 708 | − (*ppCtx)->ppMbListD = static_cast<SMB **>((*ppCtx)->pMemAlign->WelsMalloc(iNumDlayer * sizeof(SMB *), "ppMbListD")); | |
| 709 | − (*ppCtx)->ppMbListD[0] = NULL; | |
| 710 | − WELS_VERIFY_RETURN_PROC_IF(1, (*ppCtx)->ppMbListD==NULL, FreeMemorySvc(ppCtx)); | |
| 711 | − (*ppCtx)->ppMbListD[0] = static_cast<SMB*>((*ppCtx)->pMemAlign->WelsMallocz(iOverallMbNum * sizeof(SMB), "ppMbListD[0]")); | |
| 712 | − WELS_VERIFY_RETURN_PROC_IF(1, (*ppCtx)->ppMbListD[0]==NULL, FreeMemorySvc(ppCtx)); | |
| 713 | − (*ppCtx)->ppDqLayerList[0]->sMbDataP = (*ppCtx)->ppMbListD[0]; | |
| 714 | − InitMbInfo(*ppCtx, (*ppCtx)->ppMbListD[0], (*ppCtx)->ppDqLayerList[0], 0, iMbSize[iNumDlayer-1]); | |
| 715 | − for( i=1;i<iNumDlayer;i++ ){ | |
| 716 | − (*ppCtx)->ppMbListD[i] = (*ppCtx)->ppMbListD[i-1] + iMbSize[i-1]; | |
| 717 | − (*ppCtx)->ppDqLayerList[i]->sMbDataP = (*ppCtx)->ppMbListD[i]; | |
| 718 | − InitMbInfo(*ppCtx, (*ppCtx)->ppMbListD[i], (*ppCtx)->ppDqLayerList[i], i, iMbSize[iNumDlayer-1]); | |
| 719 | − } | |
| 720 | − | |
| 721 | − return 0; | |
| 722 | −} | |
| 723 | − | |
| 724 | −int32_t AllocMbCacheAligned( SMbCache *pMbCache, CMemoryAlign *pMa ) | |
| 725 | −{ | |
| 726 | − pMbCache->pCoeffLevel = (int16_t *)pMa->WelsMalloc(MB_COEFF_LIST_SIZE*sizeof(int16_t), "pMbCache->pCoeffLevel"); | |
| 727 | − WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pCoeffLevel)); | |
| 728 | − pMbCache->pMemPredMb = (uint8_t *)pMa->WelsMalloc(2*256*sizeof(uint8_t), "pMbCache->pMemPredMb"); | |
| 729 | − WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pMemPredMb)); | |
| 730 | − pMbCache->pSkipMb = (uint8_t *)pMa->WelsMalloc(384*sizeof(uint8_t), "pMbCache->pSkipMb"); | |
| 731 | − WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pSkipMb)); | |
| 732 | − pMbCache->pMemPredBlk4 = (uint8_t *)pMa->WelsMalloc(2*16*sizeof(uint8_t), "pMbCache->pMemPredBlk4"); | |
| 733 | − WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pMemPredBlk4)); | |
| 734 | − pMbCache->pBufferInterPredMe = (uint8_t *)pMa->WelsMalloc(4*640*sizeof(uint8_t), "pMbCache->pBufferInterPredMe"); | |
| 735 | − WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pBufferInterPredMe)); | |
| 736 | − pMbCache->pPrevIntra4x4PredModeFlag = (bool_t *)pMa->WelsMalloc(16*sizeof(bool_t), "pMbCache->pPrevIntra4x4PredModeFlag"); | |
| 737 | − WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pPrevIntra4x4PredModeFlag)); | |
| 738 | − pMbCache->pRemIntra4x4PredModeFlag = (int8_t *)pMa->WelsMalloc(16*sizeof(int8_t), "pMbCache->pRemIntra4x4PredModeFlag"); | |
| 739 | − WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pRemIntra4x4PredModeFlag)); | |
| 740 | − pMbCache->pDct = (SDCTCoeff *)pMa->WelsMalloc(sizeof(SDCTCoeff), "pMbCache->pDct"); | |
| 741 | − WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pDct)); | |
| 742 | − return 0; | |
| 743 | −} | |
| 744 | − | |
| 745 | −void FreeMbCache( SMbCache *pMbCache, CMemoryAlign *pMa ) | |
| 746 | −{ | |
| 747 | − if ( NULL != pMbCache->pCoeffLevel ) | |
| 748 | − { | |
| 749 | − pMa->WelsFree( pMbCache->pCoeffLevel, "pMbCache->pCoeffLevel" ); | |
| 750 | − pMbCache->pCoeffLevel = NULL; | |
| 751 | − } | |
| 752 | − if ( NULL != pMbCache->pMemPredMb ) | |
| 753 | − { | |
| 754 | − pMa->WelsFree( pMbCache->pMemPredMb, "pMbCache->pMemPredMb" ); | |
| 755 | − pMbCache->pMemPredMb = NULL; | |
| 756 | − } | |
| 757 | − if ( NULL != pMbCache->pSkipMb ) | |
| 758 | − { | |
| 759 | − pMa->WelsFree( pMbCache->pSkipMb, "pMbCache->pSkipMb" ); | |
| 760 | − pMbCache->pSkipMb = NULL; | |
| 761 | − } | |
| 762 | − if ( NULL != pMbCache->pMemPredBlk4 ) | |
| 763 | − { | |
| 764 | − pMa->WelsFree( pMbCache->pMemPredBlk4, "pMbCache->pMemPredBlk4" ); | |
| 765 | − pMbCache->pMemPredBlk4 = NULL; | |
| 766 | − } | |
| 767 | − if ( NULL != pMbCache->pBufferInterPredMe ) | |
| 768 | − { | |
| 769 | − pMa->WelsFree( pMbCache->pBufferInterPredMe, "pMbCache->pBufferInterPredMe" ); | |
| 770 | − pMbCache->pBufferInterPredMe = NULL; | |
| 771 | − } | |
| 772 | − if ( NULL != pMbCache->pPrevIntra4x4PredModeFlag ) | |
| 773 | − { | |
| 774 | − pMa->WelsFree( pMbCache->pPrevIntra4x4PredModeFlag, "pMbCache->pPrevIntra4x4PredModeFlag" ); | |
| 775 | − pMbCache->pPrevIntra4x4PredModeFlag = NULL; | |
| 776 | − } | |
| 777 | − if ( NULL != pMbCache->pRemIntra4x4PredModeFlag ) | |
| 778 | − { | |
| 779 | − pMa->WelsFree( pMbCache->pRemIntra4x4PredModeFlag, "pMbCache->pRemIntra4x4PredModeFlag" ); | |
| 780 | − pMbCache->pRemIntra4x4PredModeFlag = NULL; | |
| 781 | − } | |
| 782 | − if ( NULL != pMbCache->pDct ) | |
| 783 | − { | |
| 784 | − pMa->WelsFree( pMbCache->pDct, "pMbCache->pDct" ); | |
| 785 | − pMbCache->pDct = NULL; | |
| 786 | − } | |
| 787 | −} | |
| 788 | − | |
| 789 | − | |
| 790 | −/*! | |
| 791 | − * \brief initialize ppDqLayerList and slicepEncCtx_list due to count number of layers available | |
| 792 | − * \pParam pCtx sWelsEncCtx* | |
| 793 | − * \return 0 - successful; otherwise failed | |
| 794 | − */ | |
| 795 | −static inline int32_t InitDqLayers( sWelsEncCtx **ppCtx ) | |
| 796 | −{ | |
| 797 | − SWelsSvcCodingParam *pParam = NULL; | |
| 798 | − SWelsSPS *pSps = NULL; | |
| 799 | − SSubsetSps *pSubsetSps = NULL; | |
| 800 | − SWelsPPS *pPps = NULL; | |
| 801 | − CMemoryAlign *pMa = NULL; | |
| 802 | − SStrideTables *pStrideTab = NULL; | |
| 803 | − int32_t iDlayerCount = 0; | |
| 804 | − int32_t iDlayerIndex = 0; | |
| 805 | − uint32_t iSpsId = 0; | |
| 806 | − uint32_t iPpsId = 0; | |
| 807 | − uint32_t iNumRef = 0; | |
| 808 | − int32_t iResult = 0; | |
| 809 | − | |
| 810 | − if ( NULL == ppCtx || NULL == *ppCtx ) | |
| 811 | − return 1; | |
| 812 | − | |
| 813 | − pMa = (*ppCtx)->pMemAlign; | |
| 814 | − pParam = (*ppCtx)->pSvcParam; | |
| 815 | − iDlayerCount = pParam->iNumDependencyLayer; | |
| 816 | − iNumRef = pParam->iNumRefFrame; | |
| 817 | −// highest_layers_in_temporal = 1 + WELS_MAX(pParam->iDecompStages, 1); | |
| 818 | − pStrideTab = (*ppCtx)->pStrideTab; | |
| 819 | − | |
| 820 | − iDlayerIndex = 0; | |
| 821 | − while (iDlayerIndex < iDlayerCount) | |
| 822 | − { | |
| 823 | − SRefList *pRefList = NULL; | |
| 824 | − uint32_t i = 0; | |
| 825 | − const int32_t kiWidth = pParam->sDependencyLayers[iDlayerIndex].iFrameWidth; | |
| 826 | − const int32_t kiHeight = pParam->sDependencyLayers[iDlayerIndex].iFrameHeight; | |
| 827 | − int32_t iPicWidth = WELS_ALIGN(kiWidth, MB_WIDTH_LUMA) + (PADDING_LENGTH<<1); // with iWidth of horizon | |
| 828 | − int32_t iPicChromaWidth = iPicWidth >> 1; | |
| 829 | − | |
| 830 | − iPicWidth = WELS_ALIGN( iPicWidth, 32 ); // 32(or 16 for chroma below) to match original imp. here instead of iCacheLineSize | |
| 831 | − iPicChromaWidth = WELS_ALIGN( iPicChromaWidth, 16 ); | |
| 832 | − | |
| 833 | − WelsGetEncBlockStrideOffset( (*ppCtx)->pStrideTab->pStrideEncBlockOffset[iDlayerIndex], iPicWidth, iPicChromaWidth); | |
| 834 | − | |
| 835 | − // pRef list | |
| 836 | − pRefList = (SRefList *)pMa->WelsMallocz( sizeof(SRefList), "pRefList" ); | |
| 837 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pRefList), FreeMemorySvc(ppCtx) ) | |
| 838 | − | |
| 839 | − do { | |
| 840 | − pRefList->pRef[i] = AllocPicture( pMa, kiWidth, kiHeight, true ); // to use actual size of current layer | |
| 841 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pRefList->pRef[i]), FreeMemorySvc(ppCtx) ) | |
| 842 | − ++ i; | |
| 843 | − } while(i < 1 + iNumRef); | |
| 844 | − | |
| 845 | − pRefList->pNextBuffer = pRefList->pRef[0]; | |
| 846 | − (*ppCtx)->ppRefPicListExt[iDlayerIndex] = pRefList; | |
| 847 | − ++ iDlayerIndex; | |
| 848 | − } | |
| 849 | − | |
| 850 | − // for I420 based source spatial pictures | |
| 851 | − if ( AllocSpatialPictures( ppCtx, pParam ) ) | |
| 852 | − { | |
| 853 | − FreeMemorySvc( ppCtx ); | |
| 854 | − return 1; | |
| 855 | − } | |
| 856 | − | |
| 857 | − iDlayerIndex = 0; | |
| 858 | − while (iDlayerIndex < iDlayerCount) { | |
| 859 | − SDqLayer *pDqLayer = NULL; | |
| 860 | − SDLayerParam *pDlayer = &pParam->sDependencyLayers[iDlayerIndex]; | |
| 861 | − const int32_t kiMbW = (pDlayer->iFrameWidth + 0x0f) >> 4; | |
| 862 | − const int32_t kiMbH = (pDlayer->iFrameHeight + 0x0f) >> 4; | |
| 863 | − int32_t iMaxSliceNum = 1; | |
| 864 | − const int32_t kiSliceNum = GetInitialSliceNum( kiMbW, kiMbH, &pDlayer->sMso ); | |
| 865 | − if ( iMaxSliceNum < kiSliceNum ) | |
| 866 | − iMaxSliceNum = kiSliceNum; | |
| 867 | − | |
| 868 | − // pDq layers list | |
| 869 | − pDqLayer = (SDqLayer *)pMa->WelsMallocz( sizeof(SDqLayer), "pDqLayer" ); | |
| 870 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pDqLayer), FreeMemorySvc(ppCtx) ) | |
| 871 | − | |
| 872 | − // for dynamic slicing mode | |
| 873 | − if ( SM_DYN_SLICE == pDlayer->sMso.uiSliceMode ) | |
| 874 | − { | |
| 875 | − const int32_t iSize = pParam->iCountThreadsNum * sizeof(int32_t); | |
| 876 | − | |
| 877 | − pDqLayer->pNumSliceCodedOfPartition = (int32_t *)pMa->WelsMallocz( iSize, "pNumSliceCodedOfPartition" ); | |
| 878 | − pDqLayer->pLastCodedMbIdxOfPartition = (int32_t *)pMa->WelsMallocz( iSize, "pLastCodedMbIdxOfPartition" ); | |
| 879 | − pDqLayer->pLastMbIdxOfPartition = (int32_t *)pMa->WelsMallocz( iSize, "pLastMbIdxOfPartition" ); | |
| 880 | − | |
| 881 | − WELS_VERIFY_RETURN_PROC_IF( 1, | |
| 882 | − (NULL == pDqLayer->pNumSliceCodedOfPartition || | |
| 883 | − NULL == pDqLayer->pLastCodedMbIdxOfPartition || | |
| 884 | − NULL == pDqLayer->pLastMbIdxOfPartition), | |
| 885 | − FreeMemorySvc(ppCtx) ) | |
| 886 | − } | |
| 887 | − | |
| 888 | − pDqLayer->iMbWidth = kiMbW; | |
| 889 | − pDqLayer->iMbHeight = kiMbH; | |
| 890 | −#ifndef MT_ENABLED | |
| 891 | − if ( SM_DYN_SLICE == pDlayer->sMso.uiSliceMode )//wmalloc pSliceInLayer | |
| 892 | − { | |
| 893 | − SSlice *pSlice = NULL; | |
| 894 | − int32_t iSliceIdx = 0; | |
| 895 | − //wmalloc AVERSLICENUM_CONSTANT of pDqLayer->sLayerInfo.pSliceInLayer, | |
| 896 | − //wmalloc AVERSLICENUM_CONSTANT num of pSlice as initialization | |
| 897 | − //only set value for the first pSlice | |
| 898 | − pDqLayer->sLayerInfo.pSliceInLayer = (SSlice *)pMa->WelsMallocz( sizeof(SSlice) * iMaxSliceNum, "pSliceInLayer" ); | |
| 899 | − | |
| 900 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pDqLayer->sLayerInfo.pSliceInLayer), FreeMemorySvc(ppCtx) ) | |
| 901 | − { | |
| 902 | − pSlice = &pDqLayer->sLayerInfo.pSliceInLayer[0]; | |
| 903 | − pSlice->uiSliceIdx = 0; | |
| 904 | − pSlice->pSliceBsa = &(*ppCtx)->pOut->sBsWrite; | |
| 905 | − } | |
| 906 | − | |
| 907 | − while(iSliceIdx < iMaxSliceNum) | |
| 908 | − { | |
| 909 | − pSlice = &pDqLayer->sLayerInfo.pSliceInLayer[iSliceIdx]; | |
| 910 | − if ( AllocMbCacheAligned(&pSlice->sMbCacheInfo, pMa) ) | |
| 911 | − { | |
| 912 | − FreeMemorySvc(ppCtx); | |
| 913 | − return 1; | |
| 914 | − } | |
| 915 | − ++ iSliceIdx; | |
| 916 | − } | |
| 917 | − } | |
| 918 | − else | |
| 919 | −#endif//!MT_ENABLED | |
| 920 | − { | |
| 921 | − int32_t iSliceIdx = 0; | |
| 922 | − pDqLayer->sLayerInfo.pSliceInLayer = (SSlice *)pMa->WelsMallocz( sizeof(SSlice) * iMaxSliceNum, "pSliceInLayer" ); | |
| 923 | − | |
| 924 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pDqLayer->sLayerInfo.pSliceInLayer), FreeMemorySvc(ppCtx) ) | |
| 925 | − if ( iMaxSliceNum > 1 ) | |
| 926 | − { | |
| 927 | − while (iSliceIdx < iMaxSliceNum) { | |
| 928 | − SSlice *pSlice = &pDqLayer->sLayerInfo.pSliceInLayer[iSliceIdx]; | |
| 929 | − pSlice->uiSliceIdx = iSliceIdx; | |
| 930 | −#ifdef MT_ENABLED | |
| 931 | − if ( pParam->iMultipleThreadIdc > 1 ) | |
| 932 | − pSlice->pSliceBsa = &(*ppCtx)->pSliceBs[iSliceIdx].sBsWrite; | |
| 933 | − else | |
| 934 | − pSlice->pSliceBsa = &(*ppCtx)->pOut->sBsWrite; | |
| 935 | −#else | |
| 936 | − pSlice->pSliceBsa = &(*ppCtx)->pOut->sBsWrite; | |
| 937 | −#endif//MT_ENABLED | |
| 938 | − if ( AllocMbCacheAligned(&pSlice->sMbCacheInfo, pMa) ) | |
| 939 | − { | |
| 940 | − FreeMemorySvc(ppCtx); | |
| 941 | − return 1; | |
| 942 | − } | |
| 943 | − ++ iSliceIdx; | |
| 944 | − } | |
| 945 | − } | |
| 946 | − // fix issue in case single pSlice coding might be inclusive exist in variant spatial layer setting, also introducing multi-pSlice modes | |
| 947 | − else // only one pSlice | |
| 948 | − { | |
| 949 | − SSlice *pSlice = &pDqLayer->sLayerInfo.pSliceInLayer[0]; | |
| 950 | − pSlice->uiSliceIdx = 0; | |
| 951 | − pSlice->pSliceBsa = &(*ppCtx)->pOut->sBsWrite; | |
| 952 | − if ( AllocMbCacheAligned(&pSlice->sMbCacheInfo, pMa) ) | |
| 953 | − { | |
| 954 | − FreeMemorySvc(ppCtx); | |
| 955 | − return 1; | |
| 956 | − } | |
| 957 | − } | |
| 958 | − } | |
| 959 | − | |
| 960 | − //deblocking parameters initialization | |
| 961 | − //target-layer deblocking | |
| 962 | − pDqLayer->iLoopFilterDisableIdc = pParam->iLoopFilterDisableIdc; | |
| 963 | − pDqLayer->iLoopFilterAlphaC0Offset = (pParam->iLoopFilterAlphaC0Offset)<<1; | |
| 964 | − pDqLayer->iLoopFilterBetaOffset = (pParam->iLoopFilterBetaOffset)<<1; | |
| 965 | − //inter-layer deblocking | |
| 966 | − pDqLayer->uiDisableInterLayerDeblockingFilterIdc = pParam->iInterLayerLoopFilterDisableIdc; | |
| 967 | − pDqLayer->iInterLayerSliceAlphaC0Offset = (pParam->iInterLayerLoopFilterAlphaC0Offset)<<1; | |
| 968 | − pDqLayer->iInterLayerSliceBetaOffset = (pParam->iInterLayerLoopFilterBetaOffset)<<1; | |
| 969 | − //parallel deblocking | |
| 970 | − pDqLayer->bDeblockingParallelFlag = pParam->bDeblockingParallelFlag; | |
| 971 | − | |
| 972 | − //deblocking parameter adjustment | |
| 973 | − if ( SM_SINGLE_SLICE == pDlayer->sMso.uiSliceMode ) | |
| 974 | − { | |
| 975 | − //iLoopFilterDisableIdc: will be 0 or 1 under single_slice | |
| 976 | − if ( 2 == pParam->iLoopFilterDisableIdc ) | |
| 977 | − { | |
| 978 | − pDqLayer->iLoopFilterDisableIdc = 0; | |
| 979 | − } | |
| 980 | − //bDeblockingParallelFlag | |
| 981 | − pDqLayer->bDeblockingParallelFlag = false; | |
| 982 | − } | |
| 983 | − else | |
| 984 | − {//multi-pSlice | |
| 985 | −#ifdef MT_ENABLED | |
| 986 | − if ( 0 == pDqLayer->iLoopFilterDisableIdc ) | |
| 987 | − { | |
| 988 | − pDqLayer->bDeblockingParallelFlag = false; | |
| 989 | − } | |
| 990 | −#endif | |
| 991 | − } | |
| 992 | − | |
| 993 | − (*ppCtx)->ppDqLayerList[iDlayerIndex] = pDqLayer; | |
| 994 | − | |
| 995 | − ++ iDlayerIndex; | |
| 996 | − } | |
| 997 | − | |
| 998 | − // for dynamically malloc for parameter sets memory instead of maximal items for standard to reduce size, 3/18/2010 | |
| 999 | − if ( &(*ppCtx)->pSvcParam->bMgsT0OnlyStrategy ) | |
| 1000 | − { | |
| 1001 | − (*ppCtx)->pPPSArray = (SWelsPPS *)pMa->WelsMalloc( (1+iDlayerCount) * sizeof(SWelsPPS), "pPPSArray" ); | |
| 1002 | − } | |
| 1003 | − else | |
| 1004 | − { | |
| 1005 | − (*ppCtx)->pPPSArray = (SWelsPPS *)pMa->WelsMalloc( iDlayerCount * sizeof(SWelsPPS), "pPPSArray" ); | |
| 1006 | − } | |
| 1007 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc(ppCtx) ) | |
| 1008 | − | |
| 1009 | − (*ppCtx)->pSpsArray = (SWelsSPS *)pMa->WelsMalloc( sizeof(SWelsSPS), "pSpsArray" ); | |
| 1010 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc(ppCtx) ) | |
| 1011 | − if ( iDlayerCount > 1 ) | |
| 1012 | − { | |
| 1013 | − (*ppCtx)->pSubsetArray = (SSubsetSps *)pMa->WelsMalloc( (iDlayerCount-1) * sizeof(SSubsetSps), "pSubsetArray" ); | |
| 1014 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pSubsetArray), FreeMemorySvc(ppCtx) ) | |
| 1015 | − } | |
| 1016 | − | |
| 1017 | − (*ppCtx)->pDqIdcMap = (SDqIdc *)pMa->WelsMallocz( iDlayerCount * sizeof(SDqIdc), "pDqIdcMap" ); | |
| 1018 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pDqIdcMap), FreeMemorySvc(ppCtx) ) | |
| 1019 | − | |
| 1020 | − iDlayerIndex = 0; | |
| 1021 | − while (iDlayerIndex < iDlayerCount) { | |
| 1022 | − SDqIdc *pDqIdc = &(*ppCtx)->pDqIdcMap[iDlayerIndex]; | |
| 1023 | − const bool_t bUseSubsetSps = (iDlayerIndex > BASE_DEPENDENCY_ID); | |
| 1024 | − SDLayerParam *pDlayerParam = &pParam->sDependencyLayers[iDlayerIndex]; | |
| 1025 | − | |
| 1026 | − pDqIdc->uiSpatialId = iDlayerIndex; | |
| 1027 | − pPps = &(*ppCtx)->pPPSArray[iPpsId]; | |
| 1028 | − if ( !bUseSubsetSps ) | |
| 1029 | − { | |
| 1030 | − pSps = &(*ppCtx)->pSpsArray[iSpsId]; | |
| 1031 | − } | |
| 1032 | − else | |
| 1033 | − { | |
| 1034 | − pSubsetSps = &(*ppCtx)->pSubsetArray[iSpsId]; | |
| 1035 | − pSps = &pSubsetSps->pSps; | |
| 1036 | − } | |
| 1037 | − | |
| 1038 | − // Need port pSps/pPps initialization due to spatial scalability changed | |
| 1039 | − if ( !bUseSubsetSps ) | |
| 1040 | − { | |
| 1041 | − WelsInitSps( pSps, pDlayerParam, pParam->uiIntraPeriod, pParam->iNumRefFrame, iSpsId, | |
| 1042 | − pParam->bEnableFrameCroppingFlag, pParam->bEnableRc ); | |
| 1043 | − | |
| 1044 | − if( iDlayerCount > 1 ) | |
| 1045 | − { | |
| 1046 | − pSps->bConstraintSet0Flag = true; | |
| 1047 | − pSps->bConstraintSet1Flag = true; | |
| 1048 | − pSps->bConstraintSet2Flag = true; | |
| 1049 | − } | |
| 1050 | − } | |
| 1051 | − else | |
| 1052 | − { | |
| 1053 | − WelsInitSubsetSps( pSubsetSps, pDlayerParam, pParam->uiIntraPeriod, pParam->iNumRefFrame, iSpsId, | |
| 1054 | − pParam->bEnableFrameCroppingFlag, pParam->bEnableRc ); | |
| 1055 | − } | |
| 1056 | − | |
| 1057 | − // initialize pPps | |
| 1058 | − WelsInitPps( pPps, pSps, pSubsetSps, iPpsId, true, bUseSubsetSps ); | |
| 1059 | − | |
| 1060 | − // Not using FMO in SVC coding so far, come back if need FMO | |
| 1061 | − { | |
| 1062 | − iResult = InitSlicePEncCtx( &(*ppCtx)->pSliceCtxList[iDlayerIndex], | |
| 1063 | − (*ppCtx)->pMemAlign, | |
| 1064 | − false, | |
| 1065 | − pSps->iMbWidth, | |
| 1066 | − pSps->iMbHeight, | |
| 1067 | − &(pDlayerParam->sMso), | |
| 1068 | − pPps ); | |
| 1069 | − if ( iResult ) | |
| 1070 | − { | |
| 1071 | − WelsLog( *ppCtx, WELS_LOG_WARNING, "InitDqLayers(), InitSlicePEncCtx failed(%d)!", iResult ); | |
| 1072 | − FreeMemorySvc( ppCtx ); | |
| 1073 | − return 1; | |
| 1074 | − } | |
| 1075 | − (*ppCtx)->ppDqLayerList[iDlayerIndex]->pSliceEncCtx = &(*ppCtx)->pSliceCtxList[iDlayerIndex]; | |
| 1076 | − } | |
| 1077 | − pDqIdc->iSpsId = iSpsId; | |
| 1078 | − pDqIdc->iPpsId = iPpsId; | |
| 1079 | − | |
| 1080 | − (*ppCtx)->sPSOVector.bPpsIdMappingIntoSubsetsps[iPpsId] = bUseSubsetSps; | |
| 1081 | − | |
| 1082 | − if ( bUseSubsetSps ) | |
| 1083 | − ++ iSpsId; | |
| 1084 | − ++ iPpsId; | |
| 1085 | − ++ (*ppCtx)->iSpsNum; | |
| 1086 | − ++ (*ppCtx)->iPpsNum; | |
| 1087 | − | |
| 1088 | − ++ iDlayerIndex; | |
| 1089 | − } | |
| 1090 | − return 0; | |
| 1091 | −} | |
| 1092 | − | |
| 1093 | −int32_t AllocStrideTables( sWelsEncCtx **ppCtx, const int32_t kiNumSpatialLayers ) | |
| 1094 | −{ | |
| 1095 | − CMemoryAlign *pMa = (*ppCtx)->pMemAlign; | |
| 1096 | − SWelsSvcCodingParam *pParam = (*ppCtx)->pSvcParam; | |
| 1097 | − SStrideTables *pPtr = NULL; | |
| 1098 | − int16_t *pTmpRow = NULL, *pRowX = NULL, *pRowY = NULL, *p = NULL; | |
| 1099 | − uint8_t *pBase = NULL; | |
| 1100 | − uint8_t *pBaseDec = NULL, *pBaseEnc = NULL, *pBaseMbX = NULL, *pBaseMbY = NULL; | |
| 1101 | − struct { | |
| 1102 | − int32_t iMbWidth; | |
| 1103 | − int32_t iCountMbNum; // count number of SMB in each spatial | |
| 1104 | − int32_t iSizeAllMbAlignCache; // cache line size aligned in each spatial | |
| 1105 | − } sMbSizeMap[MAX_DEPENDENCY_LAYER] = {0}; | |
| 1106 | − int32_t iLineSizeY[MAX_DEPENDENCY_LAYER][2] = {0}; | |
| 1107 | − int32_t iLineSizeUV[MAX_DEPENDENCY_LAYER][2]= {0}; | |
| 1108 | − int32_t iMapSpatialIdx[MAX_DEPENDENCY_LAYER][2] = {0}; | |
| 1109 | − int32_t iSizeDec = 0; | |
| 1110 | − int32_t iSizeEnc = 0; | |
| 1111 | − int32_t iCountLayersNeedCs[2] = {0}; | |
| 1112 | − const int32_t kiUnit1Size = 24 * sizeof(int32_t); | |
| 1113 | − int32_t iUnit2Size = 0; | |
| 1114 | − int32_t iNeedAllocSize = 0; | |
| 1115 | − int32_t iRowSize = 0; | |
| 1116 | − int16_t iMaxMbWidth = 0; | |
| 1117 | − int16_t iMaxMbHeight = 0; | |
| 1118 | − int32_t i = 0; | |
| 1119 | − int32_t iSpatialIdx = 0; | |
| 1120 | − int32_t iTemporalIdx = 0; | |
| 1121 | − int32_t iCntTid = 0; | |
| 1122 | − | |
| 1123 | − if ( kiNumSpatialLayers <= 0 || kiNumSpatialLayers > MAX_DEPENDENCY_LAYER) | |
| 1124 | − return 1; | |
| 1125 | − | |
| 1126 | − pPtr = (SStrideTables *)pMa->WelsMalloc(sizeof(SStrideTables), "SStrideTables"); | |
| 1127 | − if (NULL == pPtr) | |
| 1128 | − return 1; | |
| 1129 | − (*ppCtx)->pStrideTab = pPtr; | |
| 1130 | − | |
| 1131 | − iCntTid = pParam->iNumTemporalLayer > 1 ? 2 : 1; | |
| 1132 | − | |
| 1133 | − iSpatialIdx = 0; | |
| 1134 | − while (iSpatialIdx < kiNumSpatialLayers) { | |
| 1135 | − const int32_t kiTmpWidth = (pParam->sDependencyLayers[iSpatialIdx].iFrameWidth + 15) >> 4; | |
| 1136 | − const int32_t kiTmpHeight= (pParam->sDependencyLayers[iSpatialIdx].iFrameHeight + 15) >> 4; | |
| 1137 | − int32_t iNumMb = kiTmpWidth * kiTmpHeight; | |
| 1138 | − | |
| 1139 | − sMbSizeMap[iSpatialIdx].iMbWidth = kiTmpWidth; | |
| 1140 | − sMbSizeMap[iSpatialIdx].iCountMbNum = iNumMb; | |
| 1141 | − | |
| 1142 | − iNumMb *= sizeof(int16_t); | |
| 1143 | − sMbSizeMap[iSpatialIdx].iSizeAllMbAlignCache = iNumMb; | |
| 1144 | − iUnit2Size += iNumMb; | |
| 1145 | − | |
| 1146 | − ++ iSpatialIdx; | |
| 1147 | − } | |
| 1148 | − | |
| 1149 | − // Adaptive size_cs, size_fdec by implementation dependency | |
| 1150 | − iTemporalIdx= 0; | |
| 1151 | − while ( iTemporalIdx < iCntTid ) | |
| 1152 | − { | |
| 1153 | − const bool_t kbBaseTemporalFlag = (iTemporalIdx == 0); | |
| 1154 | − | |
| 1155 | − iSpatialIdx = 0; | |
| 1156 | − while ( iSpatialIdx < kiNumSpatialLayers ) | |
| 1157 | − { | |
| 1158 | − SDLayerParam *fDlp = &pParam->sDependencyLayers[iSpatialIdx]; | |
| 1159 | − | |
| 1160 | − const int32_t kiWidthPad = WELS_ALIGN( fDlp->iFrameWidth, 16 ) + (PADDING_LENGTH<<1); | |
| 1161 | − iLineSizeY[iSpatialIdx][kbBaseTemporalFlag] = WELS_ALIGN( kiWidthPad, 32 ); | |
| 1162 | − iLineSizeUV[iSpatialIdx][kbBaseTemporalFlag]= WELS_ALIGN( (kiWidthPad>>1), 16 ); | |
| 1163 | − | |
| 1164 | − iMapSpatialIdx[iCountLayersNeedCs[kbBaseTemporalFlag]][kbBaseTemporalFlag] = iSpatialIdx; | |
| 1165 | − ++ iCountLayersNeedCs[kbBaseTemporalFlag]; | |
| 1166 | − ++ iSpatialIdx; | |
| 1167 | − } | |
| 1168 | − ++ iTemporalIdx; | |
| 1169 | − } | |
| 1170 | − iSizeDec= kiUnit1Size * (iCountLayersNeedCs[0] + iCountLayersNeedCs[1]); | |
| 1171 | − iSizeEnc= kiUnit1Size * kiNumSpatialLayers; | |
| 1172 | − | |
| 1173 | − iNeedAllocSize = iSizeDec + iSizeEnc + (iUnit2Size << 1); | |
| 1174 | − | |
| 1175 | − pBase = (uint8_t *)pMa->WelsMalloc( iNeedAllocSize, "pBase" ); | |
| 1176 | − if ( NULL == pBase ) | |
| 1177 | − { | |
| 1178 | − return 1; | |
| 1179 | − } | |
| 1180 | − | |
| 1181 | − pBaseDec= pBase; // iCountLayersNeedCs | |
| 1182 | − pBaseEnc= pBaseDec + iSizeDec; // iNumSpatialLayers | |
| 1183 | − pBaseMbX = pBaseEnc + iSizeEnc; // iNumSpatialLayers | |
| 1184 | − pBaseMbY = pBaseMbX + iUnit2Size; // iNumSpatialLayers | |
| 1185 | − | |
| 1186 | − iTemporalIdx= 0; | |
| 1187 | − while ( iTemporalIdx < iCntTid ) | |
| 1188 | − { | |
| 1189 | − const bool_t kbBaseTemporalFlag = (iTemporalIdx == 0); | |
| 1190 | − | |
| 1191 | − iSpatialIdx = 0; | |
| 1192 | − while ( iSpatialIdx < iCountLayersNeedCs[kbBaseTemporalFlag] ) | |
| 1193 | − { | |
| 1194 | − const int32_t kiActualSpatialIdx = iMapSpatialIdx[iSpatialIdx][kbBaseTemporalFlag]; | |
| 1195 | − const int32_t kiLumaWidth = iLineSizeY[kiActualSpatialIdx][kbBaseTemporalFlag]; | |
| 1196 | − const int32_t kiChromaWidth = iLineSizeUV[kiActualSpatialIdx][kbBaseTemporalFlag]; | |
| 1197 | − | |
| 1198 | − WelsGetEncBlockStrideOffset( (int32_t *)pBaseDec, kiLumaWidth, kiChromaWidth ); | |
| 1199 | − | |
| 1200 | − pPtr->pStrideDecBlockOffset[kiActualSpatialIdx][kbBaseTemporalFlag] = (int32_t *)pBaseDec; | |
| 1201 | − pBaseDec+= kiUnit1Size; | |
| 1202 | − | |
| 1203 | − ++ iSpatialIdx; | |
| 1204 | − } | |
| 1205 | − ++ iTemporalIdx; | |
| 1206 | − } | |
| 1207 | − iTemporalIdx= 0; | |
| 1208 | − while ( iTemporalIdx < iCntTid ) | |
| 1209 | − { | |
| 1210 | − const bool_t kbBaseTemporalFlag = (iTemporalIdx == 0); | |
| 1211 | − | |
| 1212 | − iSpatialIdx = 0; | |
| 1213 | − while (iSpatialIdx < kiNumSpatialLayers) | |
| 1214 | − { | |
| 1215 | − int32_t iMatchIndex = 0; | |
| 1216 | − bool_t bInMap = false; | |
| 1217 | − bool_t bMatchFlag = false; | |
| 1218 | − | |
| 1219 | − i = 0; | |
| 1220 | − while ( i < iCountLayersNeedCs[kbBaseTemporalFlag] ) | |
| 1221 | − { | |
| 1222 | − const int32_t kiActualIdx = iMapSpatialIdx[i][kbBaseTemporalFlag]; | |
| 1223 | − if ( kiActualIdx == iSpatialIdx ) | |
| 1224 | − { | |
| 1225 | − bInMap = true; | |
| 1226 | − break; | |
| 1227 | − } | |
| 1228 | − if ( !bMatchFlag ) | |
| 1229 | − { | |
| 1230 | − iMatchIndex = kiActualIdx; | |
| 1231 | − bMatchFlag = true; | |
| 1232 | − } | |
| 1233 | − ++ i; | |
| 1234 | − } | |
| 1235 | − | |
| 1236 | − if ( bInMap ) | |
| 1237 | − { | |
| 1238 | − ++ iSpatialIdx; | |
| 1239 | − continue; | |
| 1240 | − } | |
| 1241 | − | |
| 1242 | − // not in spatial map and assign match one to it | |
| 1243 | − pPtr->pStrideDecBlockOffset[iSpatialIdx][kbBaseTemporalFlag] = pPtr->pStrideDecBlockOffset[iMatchIndex][kbBaseTemporalFlag]; | |
| 1244 | − | |
| 1245 | − ++ iSpatialIdx; | |
| 1246 | − } | |
| 1247 | − ++ iTemporalIdx; | |
| 1248 | − } | |
| 1249 | − | |
| 1250 | − iSpatialIdx = 0; | |
| 1251 | − while ( iSpatialIdx < kiNumSpatialLayers ) | |
| 1252 | − { | |
| 1253 | − const int32_t kiAllocMbSize = sMbSizeMap[iSpatialIdx].iSizeAllMbAlignCache; | |
| 1254 | − | |
| 1255 | − pPtr->pStrideEncBlockOffset[iSpatialIdx] = (int32_t *)pBaseEnc; | |
| 1256 | − | |
| 1257 | − pPtr->pMbIndexX[iSpatialIdx] = (int16_t *)pBaseMbX; | |
| 1258 | − pPtr->pMbIndexY[iSpatialIdx] = (int16_t *)pBaseMbY; | |
| 1259 | − | |
| 1260 | − pBaseEnc += kiUnit1Size; | |
| 1261 | − pBaseMbX += kiAllocMbSize; | |
| 1262 | − pBaseMbY += kiAllocMbSize; | |
| 1263 | − | |
| 1264 | − ++ iSpatialIdx; | |
| 1265 | − } | |
| 1266 | − | |
| 1267 | − while ( iSpatialIdx < MAX_DEPENDENCY_LAYER ) | |
| 1268 | − { | |
| 1269 | − pPtr->pStrideDecBlockOffset[iSpatialIdx][0] = NULL; | |
| 1270 | − pPtr->pStrideDecBlockOffset[iSpatialIdx][1] = NULL; | |
| 1271 | − pPtr->pStrideEncBlockOffset[iSpatialIdx] = NULL; | |
| 1272 | − pPtr->pMbIndexX[iSpatialIdx] = NULL; | |
| 1273 | − pPtr->pMbIndexY[iSpatialIdx] = NULL; | |
| 1274 | − | |
| 1275 | − ++ iSpatialIdx; | |
| 1276 | − } | |
| 1277 | − | |
| 1278 | − // initialize pMbIndexX and pMbIndexY tables as below | |
| 1279 | − | |
| 1280 | − iMaxMbWidth = sMbSizeMap[kiNumSpatialLayers-1].iMbWidth; | |
| 1281 | − iMaxMbWidth = WELS_ALIGN(iMaxMbWidth, 4); // 4 loops for int16_t required introduced as below | |
| 1282 | − iRowSize = iMaxMbWidth * sizeof(int16_t); | |
| 1283 | − | |
| 1284 | − pTmpRow = (int16_t*)pMa->WelsMalloc( iRowSize, "pTmpRow" ); | |
| 1285 | − if ( NULL == pTmpRow ) | |
| 1286 | − { | |
| 1287 | − return 1; | |
| 1288 | − } | |
| 1289 | − pRowX = pTmpRow; | |
| 1290 | − pRowY = pRowX; | |
| 1291 | − // initialize pRowX & pRowY | |
| 1292 | − i = 0; | |
| 1293 | − p = pRowX; | |
| 1294 | − while ( i < iMaxMbWidth ) | |
| 1295 | − { | |
| 1296 | − *p = i; | |
| 1297 | − *(p+1) = 1+i; | |
| 1298 | − *(p+2) = 2+i; | |
| 1299 | − *(p+3) = 3+i; | |
| 1300 | − | |
| 1301 | − p += 4; | |
| 1302 | − i += 4; | |
| 1303 | − } | |
| 1304 | − | |
| 1305 | − iSpatialIdx = kiNumSpatialLayers; | |
| 1306 | − while ( --iSpatialIdx >= 0 ) | |
| 1307 | − { | |
| 1308 | − int16_t *pMbIndexX = pPtr->pMbIndexX[iSpatialIdx]; | |
| 1309 | − const int32_t kiMbWidth = sMbSizeMap[iSpatialIdx].iMbWidth; | |
| 1310 | − const int32_t kiMbHeight = sMbSizeMap[iSpatialIdx].iCountMbNum / kiMbWidth; | |
| 1311 | − const int32_t kiLineSize = kiMbWidth * sizeof(int16_t); | |
| 1312 | − | |
| 1313 | − i = 0; | |
| 1314 | − while ( i < kiMbHeight ) | |
| 1315 | − { | |
| 1316 | − memcpy( pMbIndexX, pRowX, kiLineSize ); // confirmed_safe_unsafe_usage | |
| 1317 | − | |
| 1318 | − pMbIndexX += kiMbWidth; | |
| 1319 | − ++ i; | |
| 1320 | − } | |
| 1321 | − } | |
| 1322 | − | |
| 1323 | − memset(pRowY, 0, iRowSize); | |
| 1324 | − iMaxMbHeight = sMbSizeMap[kiNumSpatialLayers-1].iCountMbNum / sMbSizeMap[kiNumSpatialLayers-1].iMbWidth; | |
| 1325 | − i = 0; | |
| 1326 | − for (;;) | |
| 1327 | − { | |
| 1328 | − ENFORCE_STACK_ALIGN_1D(int16_t, t, 4, 16) | |
| 1329 | − | |
| 1330 | − int32_t t32 = 0; | |
| 1331 | − int16_t j = 0; | |
| 1332 | − | |
| 1333 | − for ( iSpatialIdx = kiNumSpatialLayers-1; iSpatialIdx >= 0; -- iSpatialIdx ) | |
| 1334 | − { | |
| 1335 | − const int32_t kiMbWidth = sMbSizeMap[iSpatialIdx].iMbWidth; | |
| 1336 | − const int32_t kiMbHeight = sMbSizeMap[iSpatialIdx].iCountMbNum / kiMbWidth; | |
| 1337 | − const int32_t kiLineSize = kiMbWidth * sizeof(int16_t); | |
| 1338 | − int16_t *pMbIndexY = pPtr->pMbIndexY[iSpatialIdx] + i * kiMbWidth; | |
| 1339 | − | |
| 1340 | − if ( i < kiMbHeight ) | |
| 1341 | − { | |
| 1342 | − memcpy( pMbIndexY, pRowY, kiLineSize ); // confirmed_safe_unsafe_usage | |
| 1343 | − } | |
| 1344 | − } | |
| 1345 | − ++ i; | |
| 1346 | − if (i >= iMaxMbHeight) | |
| 1347 | − break; | |
| 1348 | − | |
| 1349 | − t32 = i | (i << 16); | |
| 1350 | − ST32( t , t32 ); | |
| 1351 | − ST32( t+2, t32 ); | |
| 1352 | − | |
| 1353 | − p = pRowY; | |
| 1354 | − while ( j < iMaxMbWidth ) | |
| 1355 | − { | |
| 1356 | − ST64( p, LD64(t) ); | |
| 1357 | − | |
| 1358 | − p += 4; | |
| 1359 | − j += 4; | |
| 1360 | − } | |
| 1361 | − } | |
| 1362 | − | |
| 1363 | − pMa->WelsFree( pTmpRow, "pTmpRow" ); | |
| 1364 | − pTmpRow = NULL; | |
| 1365 | − | |
| 1366 | − return 0; | |
| 1367 | −} | |
| 1368 | − | |
| 1369 | −/*! | |
| 1370 | − * \brief request specific memory for SVC | |
| 1371 | − * \pParam pEncCtx sWelsEncCtx* | |
| 1372 | − * \return successful - 0; otherwise none 0 for failed | |
| 1373 | − */ | |
| 1374 | −int32_t RequestMemorySvc( sWelsEncCtx **ppCtx ) | |
| 1375 | −{ | |
| 1376 | − SWelsSvcCodingParam *pParam = (*ppCtx)->pSvcParam; | |
| 1377 | − CMemoryAlign *pMa = (*ppCtx)->pMemAlign; | |
| 1378 | − SDLayerParam *pFinalSpatial = NULL; | |
| 1379 | − int32_t iCountBsLen = 0; | |
| 1380 | − int32_t iCountNals = 0; | |
| 1381 | − int32_t iMaxPicWidth = 0; | |
| 1382 | − int32_t iMaxPicHeight = 0; | |
| 1383 | − int32_t iCountMaxMbNum = 0; | |
| 1384 | − int32_t iIndex = 0; | |
| 1385 | − int32_t iCountLayers = 0; | |
| 1386 | − int32_t iResult = 0; | |
| 1387 | − float fCompressRatioThr = .5f; | |
| 1388 | − const int32_t kiNumDependencyLayers = pParam->iNumDependencyLayer; | |
| 1389 | − const uint32_t kuiMvdInterTableSize = ( kiNumDependencyLayers == 1 ? (1 + (648 << 1)) : (1 + (972 << 1)) ); | |
| 1390 | − const uint32_t kuiMvdCacheAlginedSize = kuiMvdInterTableSize * sizeof(uint16_t); | |
| 1391 | − int32_t iVclLayersBsSizeCount = 0; | |
| 1392 | − int32_t iNonVclLayersBsSizeCount = 0; | |
| 1393 | −#if defined(MT_ENABLED) | |
| 1394 | − int32_t iTargetSpatialBsSize = 0; | |
| 1395 | −#endif//MT_ENABLED | |
| 1396 | − | |
| 1397 | − if ( kiNumDependencyLayers < 1 || kiNumDependencyLayers > MAX_DEPENDENCY_LAYER ) | |
| 1398 | − { | |
| 1399 | − WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc() failed due to invalid iNumDependencyLayers(%d)!\n", kiNumDependencyLayers); | |
| 1400 | − FreeMemorySvc( ppCtx ); | |
| 1401 | − return 1; | |
| 1402 | − } | |
| 1403 | − | |
| 1404 | − if ( pParam->uiGopSize == 0 || ( pParam->uiIntraPeriod && ((pParam->uiIntraPeriod % pParam->uiGopSize) != 0)) ) | |
| 1405 | − { | |
| 1406 | − WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc() failed due to invalid uiIntraPeriod(%d) (=multipler of uiGopSize(%d)!", | |
| 1407 | − pParam->uiIntraPeriod, pParam->uiGopSize); | |
| 1408 | − FreeMemorySvc( ppCtx ); | |
| 1409 | − return 1; | |
| 1410 | − } | |
| 1411 | − | |
| 1412 | − pFinalSpatial = &pParam->sDependencyLayers[kiNumDependencyLayers - 1]; | |
| 1413 | − iMaxPicWidth = pFinalSpatial->iFrameWidth; | |
| 1414 | − iMaxPicHeight = pFinalSpatial->iFrameHeight; | |
| 1415 | − iCountMaxMbNum= ((15+iMaxPicWidth)>>4) * ((15+iMaxPicHeight)>>4); | |
| 1416 | − | |
| 1417 | − iResult = AcquireLayersNals( ppCtx, pParam, &iCountLayers, &iCountNals ); | |
| 1418 | − if ( iResult ) | |
| 1419 | − { | |
| 1420 | − WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), AcquireLayersNals failed(%d)!", iResult); | |
| 1421 | − FreeMemorySvc( ppCtx ); | |
| 1422 | − return 1; | |
| 1423 | − } | |
| 1424 | − | |
| 1425 | − iNonVclLayersBsSizeCount = SSEI_BUFFER_SIZE + pParam->iNumDependencyLayer * SPS_BUFFER_SIZE + (1+pParam->iNumDependencyLayer) * PPS_BUFFER_SIZE; | |
| 1426 | − | |
| 1427 | − int32_t iLayerBsSize = 0; | |
| 1428 | − iIndex = 0; | |
| 1429 | − while(iIndex < pParam->iNumDependencyLayer) | |
| 1430 | − { | |
| 1431 | − SDLayerParam *fDlp = &pParam->sDependencyLayers[iIndex]; | |
| 1432 | − | |
| 1433 | − fCompressRatioThr = COMPRESS_RATIO_DECIDED_BY_RESOLUTION(fDlp->iFrameWidth, fDlp->iFrameHeight); | |
| 1434 | − | |
| 1435 | − iLayerBsSize = WELS_ROUND( ( (3 * fDlp->iFrameWidth * fDlp->iFrameHeight)>>1) * fCompressRatioThr); | |
| 1436 | − iLayerBsSize = WELS_ALIGN(iLayerBsSize, 4); // 4 bytes alinged | |
| 1437 | − iVclLayersBsSizeCount += iLayerBsSize; | |
| 1438 | − ++ iIndex; | |
| 1439 | − } | |
| 1440 | −#if defined(MT_ENABLED) | |
| 1441 | − iTargetSpatialBsSize = iLayerBsSize; | |
| 1442 | −#endif//MT_ENABLED | |
| 1443 | − iCountBsLen = iNonVclLayersBsSizeCount + iVclLayersBsSizeCount; | |
| 1444 | − | |
| 1445 | − pParam->iNumRefFrame = WELS_CLIP3(pParam->iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM); | |
| 1446 | − | |
| 1447 | − // Output | |
| 1448 | − (*ppCtx)->pOut = (SWelsEncoderOutput *)pMa->WelsMalloc( sizeof(SWelsEncoderOutput), "SWelsEncoderOutput" ); | |
| 1449 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pOut), FreeMemorySvc(ppCtx) ) | |
| 1450 | − (*ppCtx)->pOut->pBsBuffer = (uint8_t *)pMa->WelsMalloc( iCountBsLen, "pOut->pBsBuffer" ); | |
| 1451 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pOut->pBsBuffer), FreeMemorySvc(ppCtx) ) | |
| 1452 | − (*ppCtx)->pOut->uiSize = iCountBsLen; | |
| 1453 | − (*ppCtx)->pOut->sNalList = (SWelsNalRaw *)pMa->WelsMalloc( iCountNals * sizeof(SWelsNalRaw), "pOut->sNalList" ); | |
| 1454 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pOut->sNalList), FreeMemorySvc(ppCtx) ) | |
| 1455 | − (*ppCtx)->pOut->iCountNals = iCountNals; | |
| 1456 | − (*ppCtx)->pOut->iNalIndex = 0; | |
| 1457 | − | |
| 1458 | −#ifdef MT_ENABLED | |
| 1459 | − if ( pParam->iMultipleThreadIdc > 1 ) | |
| 1460 | − { | |
| 1461 | − (*ppCtx)->pFrameBs = (uint8_t *)pMa->WelsMalloc( iCountBsLen + (iTargetSpatialBsSize * ((*ppCtx)->iMaxSliceCount-1)), "pFrameBs" ); | |
| 1462 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pFrameBs), FreeMemorySvc(ppCtx) ) | |
| 1463 | − (*ppCtx)->iFrameBsSize = iCountBsLen * (*ppCtx)->iMaxSliceCount; | |
| 1464 | − } | |
| 1465 | − else | |
| 1466 | −#endif//MT_ENABLED | |
| 1467 | − { | |
| 1468 | − (*ppCtx)->pFrameBs = (uint8_t *)pMa->WelsMalloc( iCountBsLen, "pFrameBs" ); | |
| 1469 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pFrameBs), FreeMemorySvc(ppCtx) ) | |
| 1470 | − (*ppCtx)->iFrameBsSize = iCountBsLen; | |
| 1471 | − } | |
| 1472 | − (*ppCtx)->iPosBsBuffer = 0; | |
| 1473 | − | |
| 1474 | −#ifdef MT_ENABLED | |
| 1475 | − // for pSlice bs buffers | |
| 1476 | − if ( pParam->iMultipleThreadIdc > 1 && RequestMtResource( ppCtx, pParam, iCountBsLen, iTargetSpatialBsSize ) ) | |
| 1477 | − { | |
| 1478 | − WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), RequestMtResource failed!"); | |
| 1479 | − FreeMemorySvc( ppCtx ); | |
| 1480 | − return 1; | |
| 1481 | − } | |
| 1482 | −#endif | |
| 1483 | − | |
| 1484 | − (*ppCtx)->pIntra4x4PredModeBlocks = static_cast<int8_t*> | |
| 1485 | − (pMa->WelsMallocz( iCountMaxMbNum * INTRA_4x4_MODE_NUM, "pIntra4x4PredModeBlocks" )); | |
| 1486 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pIntra4x4PredModeBlocks), FreeMemorySvc(ppCtx) ) | |
| 1487 | − | |
| 1488 | − (*ppCtx)->pNonZeroCountBlocks = static_cast<int8_t*> | |
| 1489 | − (pMa->WelsMallocz( iCountMaxMbNum * MB_LUMA_CHROMA_BLOCK4x4_NUM, "pNonZeroCountBlocks" )); | |
| 1490 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pNonZeroCountBlocks), FreeMemorySvc(ppCtx) ) | |
| 1491 | − | |
| 1492 | − (*ppCtx)->pMvUnitBlock4x4 = static_cast<SMVUnitXY*> | |
| 1493 | − (pMa->WelsMallocz( iCountMaxMbNum * 2 * MB_BLOCK4x4_NUM * sizeof(SMVUnitXY), "pMvUnitBlock4x4" )); | |
| 1494 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pMvUnitBlock4x4), FreeMemorySvc(ppCtx) ) | |
| 1495 | − | |
| 1496 | − (*ppCtx)->pRefIndexBlock4x4 = static_cast<int8_t*> | |
| 1497 | − (pMa->WelsMallocz( iCountMaxMbNum * 2 * MB_BLOCK8x8_NUM * sizeof(int8_t), "pRefIndexBlock4x4" )); | |
| 1498 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pRefIndexBlock4x4), FreeMemorySvc(ppCtx) ) | |
| 1499 | − | |
| 1500 | − (*ppCtx)->pSadCostMb = static_cast<int32_t*> | |
| 1501 | − (pMa->WelsMallocz( iCountMaxMbNum * sizeof(int32_t), "pSadCostMb" )); | |
| 1502 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pSadCostMb), FreeMemorySvc(ppCtx)) | |
| 1503 | − | |
| 1504 | − (*ppCtx)->bEncCurFrmAsIdrFlag = true; // make sure first frame is IDR | |
| 1505 | − (*ppCtx)->iGlobalQp = 26; // global qp in default | |
| 1506 | − | |
| 1507 | − (*ppCtx)->pLtr = (SLTRState *)pMa->WelsMalloc( kiNumDependencyLayers*sizeof(SLTRState), "SLTRState" ); | |
| 1508 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pLtr), FreeMemorySvc(ppCtx) ) | |
| 1509 | − int32_t i = 0; | |
| 1510 | − for( i = 0; i < kiNumDependencyLayers; i++ ) | |
| 1511 | − { | |
| 1512 | − ResetLtrState( &(*ppCtx)->pLtr[i] ); | |
| 1513 | − } | |
| 1514 | − | |
| 1515 | − (*ppCtx)->ppRefPicListExt = (SRefList**)pMa->WelsMalloc( kiNumDependencyLayers * sizeof(SRefList *), "ppRefPicListExt" ); | |
| 1516 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->ppRefPicListExt), FreeMemorySvc(ppCtx) ) | |
| 1517 | − | |
| 1518 | − // pSlice context list | |
| 1519 | − (*ppCtx)->pSliceCtxList = (SSliceCtx *)pMa->WelsMallocz( kiNumDependencyLayers * sizeof(SSliceCtx), "pSliceCtxList" ); | |
| 1520 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pSliceCtxList), FreeMemorySvc(ppCtx) ) | |
| 1521 | − | |
| 1522 | − (*ppCtx)->ppDqLayerList = (SDqLayer **)pMa->WelsMalloc( kiNumDependencyLayers * sizeof(SDqLayer *), "ppDqLayerList" ); | |
| 1523 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->ppDqLayerList), FreeMemorySvc(ppCtx) ) | |
| 1524 | − | |
| 1525 | − // stride tables | |
| 1526 | − if ( AllocStrideTables( ppCtx, kiNumDependencyLayers ) ) | |
| 1527 | − { | |
| 1528 | − WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), AllocStrideTables failed!"); | |
| 1529 | − FreeMemorySvc( ppCtx ); | |
| 1530 | − return 1; | |
| 1531 | − } | |
| 1532 | − | |
| 1533 | − //Rate control module memory allocation | |
| 1534 | − // only malloc once for RC pData, 12/14/2009 | |
| 1535 | − (*ppCtx)->pWelsSvcRc = (SWelsSvcRc *)pMa->WelsMallocz( kiNumDependencyLayers * sizeof(SWelsSvcRc), "pWelsSvcRc" ); | |
| 1536 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pWelsSvcRc), FreeMemorySvc(ppCtx) ) | |
| 1537 | − //End of Rate control module memory allocation | |
| 1538 | − | |
| 1539 | − //pVaa memory allocation | |
| 1540 | − (*ppCtx)->pVaa = (SVAAFrameInfo *)pMa->WelsMallocz( sizeof(SVAAFrameInfo), "pVaa" ); | |
| 1541 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa), FreeMemorySvc(ppCtx) ) | |
| 1542 | − | |
| 1543 | − if((*ppCtx)->pSvcParam->bEnableAdaptiveQuant)//malloc mem | |
| 1544 | − { | |
| 1545 | − (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureUnit = static_cast<SMotionTextureUnit*> | |
| 1546 | − (pMa->WelsMallocz( iCountMaxMbNum * sizeof(SMotionTextureUnit), "pVaa->sAdaptiveQuantParam.pMotionTextureUnit" )); | |
| 1547 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureUnit), FreeMemorySvc(ppCtx) ) | |
| 1548 | − (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp = static_cast<int8_t*> | |
| 1549 | − (pMa->WelsMallocz( iCountMaxMbNum * sizeof(int8_t), "pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp" )); | |
| 1550 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp), FreeMemorySvc(ppCtx) ) | |
| 1551 | − } | |
| 1552 | − | |
| 1553 | − (*ppCtx)->pVaa->pVaaBackgroundMbFlag = (int8_t *)pMa->WelsMallocz( iCountMaxMbNum * sizeof(int8_t), "pVaa->vaa_skip_mb_flag" ); | |
| 1554 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->pVaaBackgroundMbFlag), FreeMemorySvc(ppCtx) ) | |
| 1555 | − | |
| 1556 | − (*ppCtx)->pVaa->sVaaCalcInfo.pSad8x8 = static_cast<int32_t(*)[4]> | |
| 1557 | − (pMa->WelsMallocz( iCountMaxMbNum * 4 * sizeof(int32_t), "pVaa->sVaaCalcInfo.sad8x8" )); | |
| 1558 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSad8x8), FreeMemorySvc(ppCtx) ) | |
| 1559 | − (*ppCtx)->pVaa->sVaaCalcInfo.pSsd16x16 = static_cast<int32_t*> | |
| 1560 | − (pMa->WelsMallocz( iCountMaxMbNum * sizeof(int32_t), "pVaa->sVaaCalcInfo.pSsd16x16" )); | |
| 1561 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSsd16x16), FreeMemorySvc(ppCtx) ) | |
| 1562 | − (*ppCtx)->pVaa->sVaaCalcInfo.pSum16x16 = static_cast<int32_t*> | |
| 1563 | − (pMa->WelsMallocz( iCountMaxMbNum * sizeof(int32_t), "pVaa->sVaaCalcInfo.pSum16x16" )); | |
| 1564 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSum16x16), FreeMemorySvc(ppCtx) ) | |
| 1565 | − (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfSquare16x16 = static_cast<int32_t*> | |
| 1566 | − (pMa->WelsMallocz( iCountMaxMbNum * sizeof(int32_t), "pVaa->sVaaCalcInfo.pSumOfSquare16x16" )); | |
| 1567 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfSquare16x16), FreeMemorySvc(ppCtx) ) | |
| 1568 | − | |
| 1569 | − if ((*ppCtx)->pSvcParam->bEnableBackgroundDetection) //BGD control | |
| 1570 | − { | |
| 1571 | − (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfDiff8x8 = static_cast<int32_t(*)[4]> | |
| 1572 | − (pMa->WelsMallocz( iCountMaxMbNum * 4 * sizeof(int32_t), "pVaa->sVaaCalcInfo.sd_16x16" )); | |
| 1573 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfDiff8x8), FreeMemorySvc(ppCtx) ) | |
| 1574 | − (*ppCtx)->pVaa->sVaaCalcInfo.pMad8x8 = static_cast<uint8_t(*)[4]> | |
| 1575 | − (pMa->WelsMallocz( iCountMaxMbNum * 4 * sizeof(uint8_t), "pVaa->sVaaCalcInfo.mad_16x16" )); | |
| 1576 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pMad8x8), FreeMemorySvc(ppCtx) ) | |
| 1577 | − } | |
| 1578 | − | |
| 1579 | − //End of pVaa memory allocation | |
| 1580 | − | |
| 1581 | − iResult = InitDqLayers( ppCtx ); | |
| 1582 | − if ( iResult ) | |
| 1583 | − { | |
| 1584 | − WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), InitDqLayers failed(%d)!", iResult ); | |
| 1585 | − FreeMemorySvc( ppCtx ); | |
| 1586 | − return iResult; | |
| 1587 | − } | |
| 1588 | − | |
| 1589 | − if( InitMbListD( ppCtx ) ) | |
| 1590 | − { | |
| 1591 | − WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), InitMbListD failed!" ); | |
| 1592 | − FreeMemorySvc( ppCtx ); | |
| 1593 | − return 1; | |
| 1594 | − } | |
| 1595 | − | |
| 1596 | − (*ppCtx)->pMvdCostTableInter = (uint16_t *)pMa->WelsMallocz( 52 * kuiMvdCacheAlginedSize, "pMvdCostTableInter" ); | |
| 1597 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pMvdCostTableInter), FreeMemorySvc(ppCtx) ) | |
| 1598 | − MvdCostInit( (*ppCtx)->pMvdCostTableInter, kuiMvdInterTableSize ); //should put to a better place? | |
| 1599 | − | |
| 1600 | − if ( (*ppCtx)->ppRefPicListExt[0] != NULL && (*ppCtx)->ppRefPicListExt[0]->pRef[0] != NULL ) | |
| 1601 | − (*ppCtx)->pDecPic = (*ppCtx)->ppRefPicListExt[0]->pRef[0]; | |
| 1602 | − else | |
| 1603 | − (*ppCtx)->pDecPic = NULL; // error here | |
| 1604 | − | |
| 1605 | − (*ppCtx)->pSps = &(*ppCtx)->pSpsArray[0]; | |
| 1606 | − (*ppCtx)->pPps = &(*ppCtx)->pPPSArray[0]; | |
| 1607 | − | |
| 1608 | − return 0; | |
| 1609 | −} | |
| 1610 | − | |
| 1611 | − | |
| 1612 | −/*! | |
| 1613 | − * \brief free memory in SVC core encoder | |
| 1614 | − * \pParam pEncCtx sWelsEncCtx* | |
| 1615 | − * \return none | |
| 1616 | − */ | |
| 1617 | −void FreeMemorySvc( sWelsEncCtx **ppCtx ) | |
| 1618 | −{ | |
| 1619 | − if ( NULL != *ppCtx ) | |
| 1620 | − { | |
| 1621 | − sWelsEncCtx *pCtx = *ppCtx; | |
| 1622 | − CMemoryAlign *pMa = pCtx->pMemAlign; | |
| 1623 | − SWelsSvcCodingParam *pParam= pCtx->pSvcParam; | |
| 1624 | − int32_t ilayer = 0; | |
| 1625 | − | |
| 1626 | − // SStrideTables | |
| 1627 | − if ( NULL != pCtx->pStrideTab ) | |
| 1628 | − { | |
| 1629 | − if ( NULL != pCtx->pStrideTab->pStrideDecBlockOffset[0][1] ) | |
| 1630 | − { | |
| 1631 | − pMa->WelsFree( pCtx->pStrideTab->pStrideDecBlockOffset[0][1], "pBase" ); | |
| 1632 | − pCtx->pStrideTab->pStrideDecBlockOffset[0][1] = NULL; | |
| 1633 | − } | |
| 1634 | − pMa->WelsFree(pCtx->pStrideTab, "SStrideTables"); | |
| 1635 | − pCtx->pStrideTab = NULL; | |
| 1636 | − } | |
| 1637 | − // pDq idc map | |
| 1638 | − if ( NULL != pCtx->pDqIdcMap ) | |
| 1639 | − { | |
| 1640 | − pMa->WelsFree( pCtx->pDqIdcMap, "pDqIdcMap" ); | |
| 1641 | − pCtx->pDqIdcMap = NULL; | |
| 1642 | − } | |
| 1643 | − | |
| 1644 | − if ( NULL != pCtx->pOut ) | |
| 1645 | − { | |
| 1646 | − // bs pBuffer | |
| 1647 | − if ( NULL != pCtx->pOut->pBsBuffer ) | |
| 1648 | − { | |
| 1649 | − pMa->WelsFree( pCtx->pOut->pBsBuffer, "pOut->pBsBuffer" ); | |
| 1650 | − pCtx->pOut->pBsBuffer = NULL; | |
| 1651 | − } | |
| 1652 | − // NALs list | |
| 1653 | − if ( NULL != pCtx->pOut->sNalList ) | |
| 1654 | − { | |
| 1655 | − pMa->WelsFree( pCtx->pOut->sNalList, "pOut->sNalList" ); | |
| 1656 | − pCtx->pOut->sNalList = NULL; | |
| 1657 | − } | |
| 1658 | − pMa->WelsFree( pCtx->pOut, "SWelsEncoderOutput" ); | |
| 1659 | − pCtx->pOut = NULL; | |
| 1660 | − } | |
| 1661 | − | |
| 1662 | −#ifdef MT_ENABLED | |
| 1663 | − if ( pParam != NULL && pParam->iMultipleThreadIdc > 1 ) | |
| 1664 | − ReleaseMtResource( ppCtx ); | |
| 1665 | −#endif//MT_ENABLED | |
| 1666 | − | |
| 1667 | − // frame bitstream pBuffer | |
| 1668 | − if ( NULL != pCtx->pFrameBs ) | |
| 1669 | − { | |
| 1670 | − pMa->WelsFree( pCtx->pFrameBs, "pFrameBs" ); | |
| 1671 | − pCtx->pFrameBs = NULL; | |
| 1672 | − } | |
| 1673 | − | |
| 1674 | − // pSpsArray | |
| 1675 | − if ( NULL != pCtx->pSpsArray ) | |
| 1676 | − { | |
| 1677 | − pMa->WelsFree( pCtx->pSpsArray, "pSpsArray" ); | |
| 1678 | − pCtx->pSpsArray = NULL; | |
| 1679 | − } | |
| 1680 | − // pPPSArray | |
| 1681 | − if ( NULL != pCtx->pPPSArray ) | |
| 1682 | − { | |
| 1683 | − pMa->WelsFree( pCtx->pPPSArray, "pPPSArray" ); | |
| 1684 | − pCtx->pPPSArray = NULL; | |
| 1685 | − } | |
| 1686 | − // subset_sps_array | |
| 1687 | − if ( NULL != pCtx->pSubsetArray ) | |
| 1688 | − { | |
| 1689 | − pMa->WelsFree( pCtx->pSubsetArray, "pSubsetArray" ); | |
| 1690 | − pCtx->pSubsetArray = NULL; | |
| 1691 | − } | |
| 1692 | − | |
| 1693 | − if( NULL != pCtx->pIntra4x4PredModeBlocks ){ | |
| 1694 | − pMa->WelsFree( pCtx->pIntra4x4PredModeBlocks, "pIntra4x4PredModeBlocks" ); | |
| 1695 | − pCtx->pIntra4x4PredModeBlocks = NULL; | |
| 1696 | − } | |
| 1697 | − | |
| 1698 | − if( NULL != pCtx->pNonZeroCountBlocks ){ | |
| 1699 | − pMa->WelsFree( pCtx->pNonZeroCountBlocks, "pNonZeroCountBlocks" ); | |
| 1700 | − pCtx->pNonZeroCountBlocks = NULL; | |
| 1701 | − } | |
| 1702 | − | |
| 1703 | − if ( NULL != pCtx->pMvUnitBlock4x4) | |
| 1704 | − { | |
| 1705 | − pMa->WelsFree( pCtx->pMvUnitBlock4x4, "pMvUnitBlock4x4" ); | |
| 1706 | − pCtx->pMvUnitBlock4x4 = NULL; | |
| 1707 | − } | |
| 1708 | − | |
| 1709 | − if ( NULL != pCtx->pRefIndexBlock4x4) | |
| 1710 | − { | |
| 1711 | − pMa->WelsFree( pCtx->pRefIndexBlock4x4, "pRefIndexBlock4x4" ); | |
| 1712 | − pCtx->pRefIndexBlock4x4 = NULL; | |
| 1713 | − } | |
| 1714 | − | |
| 1715 | − if ( NULL != pCtx->ppMbListD ) | |
| 1716 | − { | |
| 1717 | − if( NULL != pCtx->ppMbListD[0] ){ | |
| 1718 | − pMa->WelsFree( pCtx->ppMbListD[0], "ppMbListD[0]" ); | |
| 1719 | − (*ppCtx)->ppMbListD[0] = NULL; | |
| 1720 | − } | |
| 1721 | − pMa->WelsFree( pCtx->ppMbListD, "ppMbListD" ); | |
| 1722 | − pCtx->ppMbListD = NULL; | |
| 1723 | − } | |
| 1724 | − | |
| 1725 | − if ( NULL != pCtx->pSadCostMb) | |
| 1726 | − { | |
| 1727 | − pMa->WelsFree( pCtx->pSadCostMb, "pSadCostMb" ); | |
| 1728 | − pCtx->pSadCostMb = NULL; | |
| 1729 | − } | |
| 1730 | − | |
| 1731 | − // SLTRState | |
| 1732 | − if ( NULL != pCtx->pLtr ) | |
| 1733 | − { | |
| 1734 | − pMa->WelsFree( pCtx->pLtr, "SLTRState" ); | |
| 1735 | − pCtx->pLtr = NULL; | |
| 1736 | − } | |
| 1737 | − | |
| 1738 | − // pDq layers list | |
| 1739 | − ilayer = 0; | |
| 1740 | − if ( NULL != pCtx->ppDqLayerList && pParam != NULL ) | |
| 1741 | − { | |
| 1742 | − while (ilayer < pParam->iNumDependencyLayer) { | |
| 1743 | − SDqLayer *pDq = pCtx->ppDqLayerList[ilayer]; | |
| 1744 | − SDLayerParam *pDlp = &pCtx->pSvcParam->sDependencyLayers[ilayer]; | |
| 1745 | − const BOOL_T kbIsDynamicSlicing = (SM_DYN_SLICE == pDlp->sMso.uiSliceMode); | |
| 1746 | − | |
| 1747 | − // pDq layers | |
| 1748 | − if ( NULL != pDq ) | |
| 1749 | − { | |
| 1750 | − if ( NULL != pDq->sLayerInfo.pSliceInLayer ) | |
| 1751 | − { | |
| 1752 | − int32_t iSliceIdx = 0; | |
| 1753 | − int32_t iSliceNum = GetInitialSliceNum( pDq->iMbWidth, pDq->iMbHeight, &pDlp->sMso ); | |
| 1754 | − if (iSliceNum < 1) | |
| 1755 | − iSliceNum = 1; | |
| 1756 | − while(iSliceIdx < iSliceNum) | |
| 1757 | − { | |
| 1758 | − SSlice *pSlice = &pDq->sLayerInfo.pSliceInLayer[iSliceIdx]; | |
| 1759 | − FreeMbCache(&pSlice->sMbCacheInfo, pMa); | |
| 1760 | − ++ iSliceIdx; | |
| 1761 | − } | |
| 1762 | − pMa->WelsFree( pDq->sLayerInfo.pSliceInLayer, "pSliceInLayer" ); | |
| 1763 | − pDq->sLayerInfo.pSliceInLayer = NULL; | |
| 1764 | − } | |
| 1765 | − if ( kbIsDynamicSlicing ) | |
| 1766 | − { | |
| 1767 | − pMa->WelsFree( pDq->pNumSliceCodedOfPartition, "pNumSliceCodedOfPartition" ); | |
| 1768 | − pDq->pNumSliceCodedOfPartition = NULL; | |
| 1769 | − pMa->WelsFree( pDq->pLastCodedMbIdxOfPartition, "pLastCodedMbIdxOfPartition" ); | |
| 1770 | − pDq->pLastCodedMbIdxOfPartition = NULL; | |
| 1771 | − pMa->WelsFree( pDq->pLastMbIdxOfPartition, "pLastMbIdxOfPartition" ); | |
| 1772 | − pDq->pLastMbIdxOfPartition = NULL; | |
| 1773 | − } | |
| 1774 | − | |
| 1775 | − pMa->WelsFree( pDq, "pDq" ); | |
| 1776 | − pDq = NULL; | |
| 1777 | − pCtx->ppDqLayerList[ilayer] = NULL; | |
| 1778 | − } | |
| 1779 | − ++ ilayer; | |
| 1780 | − } | |
| 1781 | − pMa->WelsFree( pCtx->ppDqLayerList, "ppDqLayerList" ); | |
| 1782 | − pCtx->ppDqLayerList = NULL; | |
| 1783 | − } | |
| 1784 | − FreeSpatialPictures( pCtx ); | |
| 1785 | − | |
| 1786 | − // reference picture list extension | |
| 1787 | − if ( NULL != pCtx->ppRefPicListExt && pParam != NULL ) | |
| 1788 | − { | |
| 1789 | − ilayer = 0; | |
| 1790 | − while (ilayer < pParam->iNumDependencyLayer) { | |
| 1791 | − SRefList *pRefList = pCtx->ppRefPicListExt[ilayer]; | |
| 1792 | − if ( NULL != pRefList ) | |
| 1793 | − { | |
| 1794 | − int32_t iRef = 0; | |
| 1795 | − do { | |
| 1796 | − if ( pRefList->pRef[iRef] != NULL ) | |
| 1797 | − { | |
| 1798 | − FreePicture( pMa, &pRefList->pRef[iRef] ); | |
| 1799 | − } | |
| 1800 | − ++ iRef; | |
| 1801 | − } while(iRef < 1 + pParam->iNumRefFrame); | |
| 1802 | − | |
| 1803 | − pMa->WelsFree( pCtx->ppRefPicListExt[ilayer], "ppRefPicListExt[]" ); | |
| 1804 | − pCtx->ppRefPicListExt[ilayer] = NULL; | |
| 1805 | − } | |
| 1806 | − ++ ilayer; | |
| 1807 | − } | |
| 1808 | − | |
| 1809 | − pMa->WelsFree( pCtx->ppRefPicListExt, "ppRefPicListExt" ); | |
| 1810 | − pCtx->ppRefPicListExt = NULL; | |
| 1811 | − } | |
| 1812 | − | |
| 1813 | − // pSlice context list | |
| 1814 | − if ( NULL != pCtx->pSliceCtxList && pParam != NULL ) | |
| 1815 | − { | |
| 1816 | − ilayer = 0; | |
| 1817 | − while (ilayer < pParam->iNumDependencyLayer) { | |
| 1818 | − SSliceCtx *pSliceCtx = &pCtx->pSliceCtxList[ilayer]; | |
| 1819 | − if ( NULL != pSliceCtx ) | |
| 1820 | − UninitSlicePEncCtx( pSliceCtx, pMa ); | |
| 1821 | − ++ ilayer; | |
| 1822 | − } | |
| 1823 | − pMa->WelsFree( pCtx->pSliceCtxList, "pSliceCtxList" ); | |
| 1824 | − pCtx->pSliceCtxList = NULL; | |
| 1825 | − } | |
| 1826 | − | |
| 1827 | − // VAA | |
| 1828 | − if ( NULL != pCtx->pVaa ) | |
| 1829 | − { | |
| 1830 | − if(pCtx->pSvcParam->bEnableAdaptiveQuant)//free mem | |
| 1831 | − { | |
| 1832 | − pMa->WelsFree( pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureUnit, "pVaa->sAdaptiveQuantParam.pMotionTextureUnit" ); | |
| 1833 | − pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureUnit = NULL; | |
| 1834 | − pMa->WelsFree( pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp, "pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp" ); | |
| 1835 | − pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp = NULL; | |
| 1836 | − } | |
| 1837 | − | |
| 1838 | − pMa->WelsFree( pCtx->pVaa->pVaaBackgroundMbFlag, "pVaa->pVaaBackgroundMbFlag"); | |
| 1839 | − pCtx->pVaa->pVaaBackgroundMbFlag = NULL; | |
| 1840 | − pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pSad8x8, "pVaa->sVaaCalcInfo.sad8x8" ); | |
| 1841 | − pCtx->pVaa->sVaaCalcInfo.pSad8x8 = NULL; | |
| 1842 | − pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pSsd16x16, "pVaa->sVaaCalcInfo.pSsd16x16" ); | |
| 1843 | − pCtx->pVaa->sVaaCalcInfo.pSsd16x16 = NULL; | |
| 1844 | − pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pSum16x16, "pVaa->sVaaCalcInfo.pSum16x16" ); | |
| 1845 | − pCtx->pVaa->sVaaCalcInfo.pSum16x16 = NULL; | |
| 1846 | − pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pSumOfSquare16x16, "pVaa->sVaaCalcInfo.pSumOfSquare16x16" ); | |
| 1847 | − pCtx->pVaa->sVaaCalcInfo.pSumOfSquare16x16 = NULL; | |
| 1848 | − | |
| 1849 | − if (pCtx->pSvcParam->bEnableBackgroundDetection) //BGD control | |
| 1850 | − { | |
| 1851 | − pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pSumOfDiff8x8, "pVaa->sVaaCalcInfo.pSumOfDiff8x8" ); | |
| 1852 | − pCtx->pVaa->sVaaCalcInfo.pSumOfDiff8x8 = NULL; | |
| 1853 | − pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pMad8x8, "pVaa->sVaaCalcInfo.pMad8x8" ); | |
| 1854 | − pCtx->pVaa->sVaaCalcInfo.pMad8x8 = NULL; | |
| 1855 | − } | |
| 1856 | − | |
| 1857 | − pMa->WelsFree( pCtx->pVaa, "pVaa" ); | |
| 1858 | − pCtx->pVaa = NULL; | |
| 1859 | − } | |
| 1860 | − | |
| 1861 | − WelsRcFreeMemory(pCtx); | |
| 1862 | − // rate control module memory free | |
| 1863 | − if ( NULL != pCtx->pWelsSvcRc ) | |
| 1864 | − { | |
| 1865 | − pMa->WelsFree( pCtx->pWelsSvcRc, "pWelsSvcRc" ); | |
| 1866 | − pCtx->pWelsSvcRc = NULL; | |
| 1867 | − } | |
| 1868 | − | |
| 1869 | − /* MVD cost tables for Inter */ | |
| 1870 | − if ( NULL != pCtx->pMvdCostTableInter ) | |
| 1871 | − { | |
| 1872 | − pMa->WelsFree( pCtx->pMvdCostTableInter, "pMvdCostTableInter" ); | |
| 1873 | − pCtx->pMvdCostTableInter = NULL; | |
| 1874 | − } | |
| 1875 | − | |
| 1876 | −#ifdef ENABLE_TRACE_FILE | |
| 1877 | − if ( NULL != pCtx->pFileLog ) | |
| 1878 | − { | |
| 1879 | − fclose( pCtx->pFileLog ); | |
| 1880 | − pCtx->pFileLog = NULL; | |
| 1881 | − } | |
| 1882 | − pCtx->uiSizeLog = 0; | |
| 1883 | −#endif//ENABLE_TRACE_FILE | |
| 1884 | − | |
| 1885 | − FreeCodingParam( &pCtx->pSvcParam, pMa ); | |
| 1886 | − if ( NULL != pCtx->pFuncList ) | |
| 1887 | − { | |
| 1888 | − pMa->WelsFree(pCtx->pFuncList, "SWelsFuncPtrList"); | |
| 1889 | − pCtx->pFuncList = NULL; | |
| 1890 | − } | |
| 1891 | − | |
| 1892 | −#if defined(MEMORY_MONITOR) | |
| 1893 | − assert(pMa->WelsGetMemoryUsage() == 0); // ensure all memory free well | |
| 1894 | −#endif//MEMORY_MONITOR | |
| 1895 | − | |
| 1896 | − if ( (*ppCtx)->pMemAlign != NULL ) | |
| 1897 | − { | |
| 1898 | − WelsLog( NULL, WELS_LOG_INFO, "FreeMemorySvc(), verify memory usage (%d bytes) after free..\n", (*ppCtx)->pMemAlign->WelsGetMemoryUsage() ); | |
| 1899 | − delete (*ppCtx)->pMemAlign; | |
| 1900 | − (*ppCtx)->pMemAlign = NULL; | |
| 1901 | − } | |
| 1902 | − | |
| 1903 | − free(*ppCtx); | |
| 1904 | − *ppCtx = NULL; | |
| 1905 | − } | |
| 1906 | −} | |
| 1907 | − | |
| 1908 | −int32_t InitSliceSettings( SWelsSvcCodingParam *pCodingParam, const int32_t kiCpuCores, int16_t *pMaxSliceCount ) | |
| 1909 | −{ | |
| 1910 | − int32_t iSpatialIdx = 0, iSpatialNum = pCodingParam->iNumDependencyLayer; | |
| 1911 | − int16_t iMaxSliceCount = 0; | |
| 1912 | − | |
| 1913 | − do { | |
| 1914 | − SDLayerParam *pDlp = &pCodingParam->sDependencyLayers[iSpatialIdx]; | |
| 1915 | − SMulSliceOption *pMso = &pDlp->sMso; | |
| 1916 | − SSliceArgument *pSlcArg = &pMso->sSliceArgument; | |
| 1917 | − const int32_t kiMbWidth = (pDlp->iFrameWidth+15)>>4; | |
| 1918 | − const int32_t kiMbHeight = (pDlp->iFrameHeight+15)>>4; | |
| 1919 | − const int32_t kiMbNumInFrame = kiMbWidth * kiMbHeight; | |
| 1920 | −#if defined(MT_ENABLED) | |
| 1921 | −#if defined(DYNAMIC_SLICE_ASSIGN) | |
| 1922 | − int32_t iSliceNum = (SM_FIXEDSLCNUM_SLICE == pMso->uiSliceMode || SM_DYN_SLICE == pMso->uiSliceMode) ? kiCpuCores : pSlcArg->iSliceNum; // uiSliceNum per input has been validated at ParamValidationExt() | |
| 1923 | −#else//!DYNAMIC_SLICE_ASSIGN | |
| 1924 | − int32_t iSliceNum = (SM_DYN_SLICE == pMso->uiSliceMode) ? kiCpuCores : pSlcArg->uiSliceNum; // uiSliceNum per input has been validated at ParamValidationExt() | |
| 1925 | −#endif//DYNAMIC_SLICE_ASSIGN | |
| 1926 | −#else//!MT_ENABLED | |
| 1927 | − int16_t iSliceNum = pSlcArg->iSliceNum; // uiSliceNum per input has been validated at ParamValidationExt() | |
| 1928 | −#endif//MT_ENABLED | |
| 1929 | − | |
| 1930 | − // NOTE: Per design, in case MT/DYNAMIC_SLICE_ASSIGN enabled, for SM_FIXEDSLCNUM_SLICE mode, | |
| 1931 | − // uiSliceNum of current spatial layer settings equals to uiCpuCores number; SM_DYN_SLICE mode, | |
| 1932 | − // uiSliceNum intials as uiCpuCores also, stay tuned dynamically slicing in future | |
| 1933 | − pSlcArg->iSliceNum = iSliceNum; // used fixed one | |
| 1934 | − | |
| 1935 | − switch(pMso->uiSliceMode) | |
| 1936 | − { | |
| 1937 | − case SM_DYN_SLICE: | |
| 1938 | − iMaxSliceCount = AVERSLICENUM_CONSTRAINT; | |
| 1939 | −//#ifndef MT_ENABLED | |
| 1940 | − break; // go through for MT_ENABLED & SM_DYN_SLICE? | |
| 1941 | −//#endif//MT_ENABLED | |
| 1942 | − case SM_FIXEDSLCNUM_SLICE: | |
| 1943 | − if ( iSliceNum > iMaxSliceCount ) | |
| 1944 | − iMaxSliceCount = iSliceNum; | |
| 1945 | − // need perform check due uiSliceNum might change, although has been initialized somewhere outside | |
| 1946 | − if (pCodingParam->bEnableRc) | |
| 1947 | − { | |
| 1948 | − GomValidCheckSliceMbNum( kiMbWidth, kiMbHeight, pSlcArg ); | |
| 1949 | − } | |
| 1950 | − else | |
| 1951 | − { | |
| 1952 | − CheckFixedSliceNumMultiSliceSetting( kiMbNumInFrame, pSlcArg ); | |
| 1953 | − } | |
| 1954 | − break; | |
| 1955 | − case SM_SINGLE_SLICE: | |
| 1956 | − if ( iSliceNum > iMaxSliceCount ) | |
| 1957 | − iMaxSliceCount = iSliceNum; | |
| 1958 | − break; | |
| 1959 | − case SM_RASTER_SLICE: | |
| 1960 | − if ( iSliceNum > iMaxSliceCount ) | |
| 1961 | − iMaxSliceCount = iSliceNum; | |
| 1962 | − break; | |
| 1963 | − case SM_ROWMB_SLICE: | |
| 1964 | − if ( iSliceNum > iMaxSliceCount ) | |
| 1965 | − iMaxSliceCount = iSliceNum; | |
| 1966 | − break; | |
| 1967 | − default: | |
| 1968 | − break; | |
| 1969 | − } | |
| 1970 | − | |
| 1971 | − ++ iSpatialIdx; | |
| 1972 | − } while(iSpatialIdx < iSpatialNum); | |
| 1973 | − | |
| 1974 | −#ifdef MT_ENABLED | |
| 1975 | − pCodingParam->iCountThreadsNum = WELS_MIN(kiCpuCores, iMaxSliceCount); | |
| 1976 | − pCodingParam->iMultipleThreadIdc = pCodingParam->iCountThreadsNum; | |
| 1977 | −#else | |
| 1978 | − pCodingParam->iMultipleThreadIdc = 1; | |
| 1979 | − pCodingParam->iCountThreadsNum = 1; | |
| 1980 | −#endif//MT_ENABLED | |
| 1981 | − | |
| 1982 | −#ifndef WELS_TESTBED // for product release and non-SGE testing | |
| 1983 | − | |
| 1984 | − if ( kiCpuCores < 2 ) // single CPU core, make no sense for MT parallelization | |
| 1985 | − { | |
| 1986 | − pCodingParam->iMultipleThreadIdc = 1; | |
| 1987 | − pCodingParam->iCountThreadsNum = 1; | |
| 1988 | − } | |
| 1989 | −#endif | |
| 1990 | − | |
| 1991 | − *pMaxSliceCount = iMaxSliceCount; | |
| 1992 | − | |
| 1993 | − return 0; | |
| 1994 | −} | |
| 1995 | − | |
| 1996 | −/*! | |
| 1997 | − * \brief log output for cpu features/capabilities | |
| 1998 | − */ | |
| 1999 | −void OutputCpuFeaturesLog( uint32_t uiCpuFeatureFlags, uint32_t uiCpuCores, int32_t iCacheLineSize ) | |
| 2000 | −{ | |
| 2001 | − // welstracer output | |
| 2002 | − WelsLog(NULL, WELS_LOG_INFO, "WELS CPU features/capacities (0x%x) detected: \t" \ | |
| 2003 | − "HTT: %c, " \ | |
| 2004 | − "MMX: %c, " \ | |
| 2005 | − "MMXEX: %c, " \ | |
| 2006 | − "SSE: %c, " \ | |
| 2007 | − "SSE2: %c, " \ | |
| 2008 | − "SSE3: %c, " \ | |
| 2009 | − "SSSE3: %c, " \ | |
| 2010 | − "SSE4.1: %c, " \ | |
| 2011 | − "SSE4.2: %c, " \ | |
| 2012 | − "AVX: %c, " \ | |
| 2013 | − "FMA: %c, " \ | |
| 2014 | − "X87-FPU: %c, " \ | |
| 2015 | − "3DNOW: %c, " \ | |
| 2016 | − "3DNOWEX: %c, " \ | |
| 2017 | − "ALTIVEC: %c, " \ | |
| 2018 | − "CMOV: %c, " \ | |
| 2019 | − "MOVBE: %c, " \ | |
| 2020 | − "AES: %c, " \ | |
| 2021 | − "NUMBER OF LOGIC PROCESSORS ON CHIP: %d, " \ | |
| 2022 | − "CPU CACHE LINE SIZE (BYTES): %d\n", | |
| 2023 | − uiCpuFeatureFlags, | |
| 2024 | − (uiCpuFeatureFlags & WELS_CPU_HTT) ? 'Y' : 'N', | |
| 2025 | − (uiCpuFeatureFlags & WELS_CPU_MMX) ? 'Y' : 'N', | |
| 2026 | − (uiCpuFeatureFlags & WELS_CPU_MMXEXT) ? 'Y' : 'N', | |
| 2027 | − (uiCpuFeatureFlags & WELS_CPU_SSE) ? 'Y' : 'N', | |
| 2028 | − (uiCpuFeatureFlags & WELS_CPU_SSE2) ? 'Y' : 'N', | |
| 2029 | − (uiCpuFeatureFlags & WELS_CPU_SSE3) ? 'Y' : 'N', | |
| 2030 | − (uiCpuFeatureFlags & WELS_CPU_SSSE3) ? 'Y' : 'N', | |
| 2031 | − (uiCpuFeatureFlags & WELS_CPU_SSE41) ? 'Y' : 'N', | |
| 2032 | − (uiCpuFeatureFlags & WELS_CPU_SSE42) ? 'Y' : 'N', | |
| 2033 | − (uiCpuFeatureFlags & WELS_CPU_AVX) ? 'Y' : 'N', | |
| 2034 | − (uiCpuFeatureFlags & WELS_CPU_FMA) ? 'Y' : 'N', | |
| 2035 | − (uiCpuFeatureFlags & WELS_CPU_FPU) ? 'Y' : 'N', | |
| 2036 | − (uiCpuFeatureFlags & WELS_CPU_3DNOW) ? 'Y' : 'N', | |
| 2037 | − (uiCpuFeatureFlags & WELS_CPU_3DNOWEXT) ? 'Y' : 'N', | |
| 2038 | − (uiCpuFeatureFlags & WELS_CPU_ALTIVEC) ? 'Y' : 'N', | |
| 2039 | − (uiCpuFeatureFlags & WELS_CPU_CMOV) ? 'Y' : 'N', | |
| 2040 | − (uiCpuFeatureFlags & WELS_CPU_MOVBE) ? 'Y' : 'N', | |
| 2041 | − (uiCpuFeatureFlags & WELS_CPU_AES) ? 'Y' : 'N', | |
| 2042 | − uiCpuCores, | |
| 2043 | − iCacheLineSize ); | |
| 2044 | − | |
| 2045 | −#ifdef _DEBUG // output at console & _debug | |
| 2046 | − fprintf( stderr, "WELS CPU features/capacities (0x%x) detected: \n" \ | |
| 2047 | − "HTT: %c, " \ | |
| 2048 | − "MMX: %c, " \ | |
| 2049 | − "MMXEX: %c, " \ | |
| 2050 | − "SSE: %c, " \ | |
| 2051 | − "SSE2: %c, " \ | |
| 2052 | − "SSE3: %c, " \ | |
| 2053 | − "SSSE3: %c, " \ | |
| 2054 | − "SSE4.1: %c, " \ | |
| 2055 | − "SSE4.2: %c, " \ | |
| 2056 | − "AVX: %c, " \ | |
| 2057 | − "FMA: %c, " \ | |
| 2058 | − "X87-FPU: %c, " \ | |
| 2059 | − "3DNOW: %c, " \ | |
| 2060 | − "3DNOWEX: %c, " \ | |
| 2061 | − "ALTIVEC: %c, " \ | |
| 2062 | − "CMOV: %c, " \ | |
| 2063 | − "MOVBE: %c, " \ | |
| 2064 | − "AES: %c, " \ | |
| 2065 | − "NUMBER OF LOGIC PROCESSORS ON CHIP: %d, " \ | |
| 2066 | − "CPU CACHE LINE SIZE (BYTES): %d\n", | |
| 2067 | − uiCpuFeatureFlags, | |
| 2068 | − (uiCpuFeatureFlags & WELS_CPU_HTT) ? 'Y' : 'N', | |
| 2069 | − (uiCpuFeatureFlags & WELS_CPU_MMX) ? 'Y' : 'N', | |
| 2070 | − (uiCpuFeatureFlags & WELS_CPU_MMXEXT) ? 'Y' : 'N', | |
| 2071 | − (uiCpuFeatureFlags & WELS_CPU_SSE) ? 'Y' : 'N', | |
| 2072 | − (uiCpuFeatureFlags & WELS_CPU_SSE2) ? 'Y' : 'N', | |
| 2073 | − (uiCpuFeatureFlags & WELS_CPU_SSE3) ? 'Y' : 'N', | |
| 2074 | − (uiCpuFeatureFlags & WELS_CPU_SSSE3) ? 'Y' : 'N', | |
| 2075 | − (uiCpuFeatureFlags & WELS_CPU_SSE41) ? 'Y' : 'N', | |
| 2076 | − (uiCpuFeatureFlags & WELS_CPU_SSE42) ? 'Y' : 'N', | |
| 2077 | − (uiCpuFeatureFlags & WELS_CPU_AVX) ? 'Y' : 'N', | |
| 2078 | − (uiCpuFeatureFlags & WELS_CPU_FMA) ? 'Y' : 'N', | |
| 2079 | − (uiCpuFeatureFlags & WELS_CPU_FPU) ? 'Y' : 'N', | |
| 2080 | − (uiCpuFeatureFlags & WELS_CPU_3DNOW) ? 'Y' : 'N', | |
| 2081 | − (uiCpuFeatureFlags & WELS_CPU_3DNOWEXT) ? 'Y' : 'N', | |
| 2082 | − (uiCpuFeatureFlags & WELS_CPU_ALTIVEC) ? 'Y' : 'N', | |
| 2083 | − (uiCpuFeatureFlags & WELS_CPU_CMOV) ? 'Y' : 'N', | |
| 2084 | − (uiCpuFeatureFlags & WELS_CPU_MOVBE) ? 'Y' : 'N', | |
| 2085 | − (uiCpuFeatureFlags & WELS_CPU_AES) ? 'Y' : 'N', | |
| 2086 | − uiCpuCores, | |
| 2087 | − iCacheLineSize ); | |
| 2088 | −#endif//_DEBUG | |
| 2089 | −} | |
| 2090 | − | |
| 2091 | −/*! | |
| 2092 | − * \brief initialize Wels avc encoder core library | |
| 2093 | − * \pParam ppCtx sWelsEncCtx** | |
| 2094 | − * \pParam pParam SWelsSvcCodingParam* | |
| 2095 | − * \return successful - 0; otherwise none 0 for failed | |
| 2096 | − */ | |
| 2097 | −int32_t WelsInitEncoderExt( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pCodingParam ) | |
| 2098 | −{ | |
| 2099 | − sWelsEncCtx *pCtx = NULL; | |
| 2100 | − int32_t iRet = 0; | |
| 2101 | − uint32_t uiCpuFeatureFlags = 0; // CPU features | |
| 2102 | − int32_t uiCpuCores = 1; // number of logic processors on physical processor package, one logic processor means HTT not supported | |
| 2103 | − int32_t iCacheLineSize = 16; // on chip cache line size in byte | |
| 2104 | − int16_t iSliceNum = 1; // number of slices used | |
| 2105 | − | |
| 2106 | − if ( NULL == ppCtx || NULL == pCodingParam ) | |
| 2107 | − { | |
| 2108 | − WelsLog(NULL, WELS_LOG_ERROR, "WelsInitEncoderExt(), NULL == ppCtx(0x%p) or NULL == pCodingParam(0x%p).\n", (void *)ppCtx, (void *)pCodingParam); | |
| 2109 | − return 1; | |
| 2110 | − } | |
| 2111 | − | |
| 2112 | − iRet = ParamValidationExt( pCodingParam ); | |
| 2113 | − if ( iRet != 0 ) | |
| 2114 | − { | |
| 2115 | − WelsLog(NULL, WELS_LOG_ERROR, "WelsInitEncoderExt(), ParamValidationExt failed return %d.\n", iRet); | |
| 2116 | − return iRet; | |
| 2117 | − } | |
| 2118 | − | |
| 2119 | − // for cpu features detection, Only detect once?? | |
| 2120 | −#ifdef X86_ASM | |
| 2121 | − uiCpuFeatureFlags = WelsCPUFeatureDetect( &uiCpuCores ); // detect cpu capacity features | |
| 2122 | − if ( uiCpuFeatureFlags & WELS_CPU_CACHELINE_128 ) | |
| 2123 | − iCacheLineSize = 128; | |
| 2124 | − else if ( uiCpuFeatureFlags & WELS_CPU_CACHELINE_64 ) | |
| 2125 | − iCacheLineSize = 64; | |
| 2126 | − else if ( uiCpuFeatureFlags & WELS_CPU_CACHELINE_32 ) | |
| 2127 | − iCacheLineSize = 32; | |
| 2128 | − else if ( uiCpuFeatureFlags & WELS_CPU_CACHELINE_16 ) | |
| 2129 | − iCacheLineSize = 16; | |
| 2130 | − OutputCpuFeaturesLog( uiCpuFeatureFlags, uiCpuCores, iCacheLineSize ); | |
| 2131 | −#else | |
| 2132 | − iCacheLineSize = 16; // 16 bytes aligned in default | |
| 2133 | −#endif//X86_ASM | |
| 2134 | − | |
| 2135 | −#ifndef WELS_TESTBED | |
| 2136 | − | |
| 2137 | −#if defined(MT_ENABLED) && defined(DYNAMIC_DETECT_CPU_CORES) | |
| 2138 | − if ( pCodingParam->iMultipleThreadIdc > 0 ) | |
| 2139 | − uiCpuCores = pCodingParam->iMultipleThreadIdc; | |
| 2140 | − else | |
| 2141 | − { | |
| 2142 | − if ( uiCpuFeatureFlags == 0 ) // cpuid not supported, use high level system API as followed to detect number of pysical/logic processor | |
| 2143 | − uiCpuCores = DynamicDetectCpuCores(); | |
| 2144 | − // So far so many cpu cores up to MAX_THREADS_NUM mean for server platforms, | |
| 2145 | − // for client application here it is constrained by maximal to MAX_THREADS_NUM | |
| 2146 | − if ( uiCpuCores > MAX_THREADS_NUM ) // MAX_THREADS_NUM | |
| 2147 | − uiCpuCores = MAX_THREADS_NUM; // MAX_THREADS_NUM | |
| 2148 | − else if ( uiCpuCores < 1 ) // just for safe | |
| 2149 | − uiCpuCores = 1; | |
| 2150 | − } | |
| 2151 | −#endif//MT_ENABLED && DYNAMIC_DETECT_CPU_CORES | |
| 2152 | − | |
| 2153 | −#else//WELS_TESTBED | |
| 2154 | − | |
| 2155 | − uiCpuCores = pCodingParam->iMultipleThreadIdc; // assigned uiCpuCores from iMultipleThreadIdc from SGE testing | |
| 2156 | − | |
| 2157 | −#endif//WELS_TESTBED | |
| 2158 | − | |
| 2159 | − uiCpuCores = WELS_CLIP3(uiCpuCores, 1, MAX_THREADS_NUM); | |
| 2160 | − | |
| 2161 | − if ( InitSliceSettings(pCodingParam, uiCpuCores, &iSliceNum ) ) | |
| 2162 | − { | |
| 2163 | − WelsLog(NULL, WELS_LOG_ERROR, "WelsInitEncoderExt(), InitSliceSettings failed.\n"); | |
| 2164 | − return 1; | |
| 2165 | − } | |
| 2166 | − | |
| 2167 | − *ppCtx = NULL; | |
| 2168 | − | |
| 2169 | − pCtx = static_cast<sWelsEncCtx*>(malloc( sizeof(sWelsEncCtx) )); | |
| 2170 | − | |
| 2171 | − WELS_VERIFY_RETURN_IF(1, (NULL == pCtx)) | |
| 2172 | − memset( pCtx, 0, sizeof(sWelsEncCtx) ); | |
| 2173 | − | |
| 2174 | − pCtx->pMemAlign = new CMemoryAlign( iCacheLineSize ); | |
| 2175 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pCtx->pMemAlign), FreeMemorySvc(&pCtx) ) | |
| 2176 | − | |
| 2177 | − // for logs | |
| 2178 | −#ifdef ENABLE_TRACE_FILE | |
| 2179 | − if (wlog == WelsLogDefault) | |
| 2180 | − { | |
| 2181 | − str_t fname[MAX_FNAME_LEN] = {0}; | |
| 2182 | − | |
| 2183 | −#if defined (_MSC_VER) | |
| 2184 | −#if _MSC_VER>=1500 | |
| 2185 | − SNPRINTF(fname, MAX_FNAME_LEN, MAX_FNAME_LEN, "%swels_svc_encoder_trace.txt", pCodingParam->sTracePath ); // confirmed_safe_unsafe_usage | |
| 2186 | −#else | |
| 2187 | − SNPRINTF(fname, MAX_FNAME_LEN, "%swels_svc_encoder_trace.txt", pCodingParam->sTracePath ); // confirmed_safe_unsafe_usage | |
| 2188 | −#endif//_MSC_VER>=1500 | |
| 2189 | −#else | |
| 2190 | − //GNUC/ | |
| 2191 | − SNPRINTF(fname, MAX_FNAME_LEN, "%swels_svc_encoder_trace.txt", pCodingParam->sTracePath ); // confirmed_safe_unsafe_usage | |
| 2192 | −#endif//_MSC_VER | |
| 2193 | − | |
| 2194 | − | |
| 2195 | −#if defined(__GNUC__) | |
| 2196 | − pCtx->pFileLog = FOPEN(fname, "wt+"); | |
| 2197 | −#else//WIN32 | |
| 2198 | −#if defined(WIN32) && defined(_MSC_VER) | |
| 2199 | −#if _MSC_VER >= 1500 | |
| 2200 | − FOPEN(&pCtx->pFileLog,fname, "wt+"); | |
| 2201 | −#else | |
| 2202 | − pCtx->pFileLog = FOPEN(fname, "wt+"); | |
| 2203 | −#endif//_MSC_VER>=1500 | |
| 2204 | −#endif//WIN32 && _MSC_VER | |
| 2205 | −#endif//__GNUC__ | |
| 2206 | − pCtx->uiSizeLog = 0; | |
| 2207 | − } | |
| 2208 | −#endif//ENABLE_TRACE_FILE | |
| 2209 | − | |
| 2210 | − pCodingParam->DetermineTemporalSettings(); | |
| 2211 | − iRet = AllocCodingParam( &pCtx->pSvcParam, pCtx->pMemAlign, pCodingParam->iNumDependencyLayer ); | |
| 2212 | − if ( iRet != 0 ) | |
| 2213 | − { | |
| 2214 | − FreeMemorySvc( &pCtx ); | |
| 2215 | − return iRet; | |
| 2216 | − } | |
| 2217 | − memcpy( pCtx->pSvcParam, pCodingParam, sizeof(SWelsSvcCodingParam) ); // confirmed_safe_unsafe_usage | |
| 2218 | − | |
| 2219 | − pCtx->pFuncList = (SWelsFuncPtrList *)pCtx->pMemAlign->WelsMalloc(sizeof(SWelsFuncPtrList), "SWelsFuncPtrList"); | |
| 2220 | − if ( NULL == pCtx->pFuncList ) | |
| 2221 | − { | |
| 2222 | − FreeMemorySvc( &pCtx ); | |
| 2223 | − return 1; | |
| 2224 | − } | |
| 2225 | − InitFunctionPointers( pCtx->pFuncList, pCtx->pSvcParam, uiCpuFeatureFlags ); | |
| 2226 | − | |
| 2227 | − pCtx->iActiveThreadsNum = pCodingParam->iCountThreadsNum; | |
| 2228 | − pCtx->iMaxSliceCount = iSliceNum; | |
| 2229 | − iRet = RequestMemorySvc( &pCtx ); | |
| 2230 | − if ( iRet != 0 ) | |
| 2231 | − { | |
| 2232 | − WelsLog(pCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), RequestMemorySvc failed return %d.\n", iRet); | |
| 2233 | − FreeMemorySvc( &pCtx ); | |
| 2234 | − return iRet; | |
| 2235 | − } | |
| 2236 | − | |
| 2237 | −#ifdef MT_ENABLED | |
| 2238 | − if ( pCodingParam->iMultipleThreadIdc > 1 ) | |
| 2239 | − iRet = CreateSliceThreads( pCtx); | |
| 2240 | −#endif | |
| 2241 | − | |
| 2242 | − WelsRcInitModule( pCtx, pCtx->pSvcParam->bEnableRc ? WELS_RC_GOM : WELS_RC_DISABLE); | |
| 2243 | − | |
| 2244 | − pCtx->pVpp = new CWelsPreProcess((void *)pCtx); | |
| 2245 | − if ( pCtx->pVpp == NULL ) | |
| 2246 | − { | |
| 2247 | − WelsLog(pCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), pOut of memory in case new CWelsPreProcess().\n"); | |
| 2248 | − FreeMemorySvc( &pCtx ); | |
| 2249 | − return iRet; | |
| 2250 | − } | |
| 2251 | − | |
| 2252 | −#if defined(MEMORY_MONITOR) | |
| 2253 | − WelsLog(pCtx, WELS_LOG_INFO, "WelsInitEncoderExt() exit, overall memory usage: %lu bytes\n", sizeof(sWelsEncCtx) /* requested size from malloc() or new operator */ | |
| 2254 | − + pCtx->pMemAlign->WelsGetMemoryUsage() /* requested size from CMemoryAlign::WelsMalloc() */ | |
| 2255 | − ); | |
| 2256 | −#endif//MEMORY_MONITOR | |
| 2257 | − | |
| 2258 | − *ppCtx = pCtx; | |
| 2259 | − | |
| 2260 | − WelsLog(pCtx, WELS_LOG_DEBUG, "WelsInitEncoderExt(), pCtx= 0x%p.\n", (void *)pCtx); | |
| 2261 | − | |
| 2262 | − return 0; | |
| 2263 | −} | |
| 2264 | −/* | |
| 2265 | − * | |
| 2266 | − * status information output | |
| 2267 | − */ | |
| 2268 | −#if defined(STAT_OUTPUT) | |
| 2269 | −void StatOverallEncodingExt(sWelsEncCtx *pCtx) | |
| 2270 | −{ | |
| 2271 | − int8_t i = 0; | |
| 2272 | − int8_t j = 0; | |
| 2273 | − for (i = 0;i<pCtx->pSvcParam->iNumDependencyLayer;i++) | |
| 2274 | − { | |
| 2275 | − fprintf( stdout,"\nDependency layer : %d\n",i); | |
| 2276 | − fprintf( stdout,"Quality layer : %d\n",j); | |
| 2277 | − { | |
| 2278 | − const int32_t iCount = pCtx->sStatData[i][j].sSliceData.iSliceCount[I_SLICE] + | |
| 2279 | − pCtx->sStatData[i][j].sSliceData.iSliceCount[P_SLICE] + | |
| 2280 | − pCtx->sStatData[i][j].sSliceData.iSliceCount[B_SLICE]; | |
| 2281 | −#if defined(MB_TYPES_CHECK) | |
| 2282 | − if (iCount > 0){ | |
| 2283 | − int32_t iCountNumIMb = pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra4x4] + pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra16x16]+ pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][7]; | |
| 2284 | − int32_t iCountNumPMb = pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra4x4] + | |
| 2285 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra16x16] + | |
| 2286 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][7] + | |
| 2287 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x16] + | |
| 2288 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x8] + | |
| 2289 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x16] + | |
| 2290 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x8] + | |
| 2291 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][10] + | |
| 2292 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][PSkip]; | |
| 2293 | − int32_t count_p_mbL0 = pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x16] + | |
| 2294 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x8] + | |
| 2295 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x16] + | |
| 2296 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x8] + | |
| 2297 | − pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][10]; | |
| 2298 | − | |
| 2299 | − int32_t iMbCount = iCountNumIMb + iCountNumPMb; | |
| 2300 | − if ( iMbCount > 0 ){ | |
| 2301 | − fprintf( stderr, | |
| 2302 | − "SVC: overall Slices MBs: %d Avg\nI4x4: %.3f%% I16x16: %.3f%% IBL: %.3f%%\nP16x16: %.3f%% P16x8: %.3f%% P8x16: %.3f%% P8x8: %.3f%% SUBP8x8: %.3f%% PSKIP: %.3f%%\nILP(All): %.3f%% ILP(PL0): %.3f%% BLSKIP(PL0): %.3f%% RP(PL0): %.3f%%\n", | |
| 2303 | − iMbCount, | |
| 2304 | − (100.0f * (pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra4x4] + pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra4x4]) / iMbCount), | |
| 2305 | − (100.0f * (pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra16x16] + pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra16x16]) / iMbCount), | |
| 2306 | − (100.0f * (pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][7] + pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][7]) / iMbCount), | |
| 2307 | − (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x16] / iMbCount ), | |
| 2308 | − (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x8] / iMbCount ), | |
| 2309 | − (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x16] / iMbCount ), | |
| 2310 | − (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x8] / iMbCount), | |
| 2311 | − (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][10] / iMbCount), | |
| 2312 | − (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][PSkip] / iMbCount), | |
| 2313 | − (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][11] / iMbCount), | |
| 2314 | − (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][11] / count_p_mbL0), | |
| 2315 | − (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][8] / count_p_mbL0), | |
| 2316 | − (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][9] / count_p_mbL0) | |
| 2317 | − ); | |
| 2318 | − } | |
| 2319 | − } | |
| 2320 | −#endif //#if defined(MB_TYPES_CHECK) | |
| 2321 | − | |
| 2322 | − if (iCount > 0){ | |
| 2323 | − fprintf( stdout, "SVC: overall PSNR Y: %2.3f U: %2.3f V: %2.3f kb/s: %.1f fps: %.3f\n\n", | |
| 2324 | − (pCtx->sStatData[i][j].sQualityStat.rYPsnr[I_SLICE]+pCtx->sStatData[i][j].sQualityStat.rYPsnr[P_SLICE]+pCtx->sStatData[i][j].sQualityStat.rYPsnr[B_SLICE]) / (float)(iCount), | |
| 2325 | − (pCtx->sStatData[i][j].sQualityStat.rUPsnr[I_SLICE]+pCtx->sStatData[i][j].sQualityStat.rUPsnr[P_SLICE]+pCtx->sStatData[i][j].sQualityStat.rUPsnr[B_SLICE]) / (float)(iCount), | |
| 2326 | − (pCtx->sStatData[i][j].sQualityStat.rVPsnr[I_SLICE]+pCtx->sStatData[i][j].sQualityStat.rVPsnr[P_SLICE]+pCtx->sStatData[i][j].sQualityStat.rVPsnr[B_SLICE]) / (float)(iCount), | |
| 2327 | − 1.0f * pCtx->pSvcParam->sDependencyLayers[i].fOutputFrameRate *(pCtx->sStatData[i][j].sSliceData.iSliceSize[I_SLICE] +pCtx->sStatData[i][j].sSliceData.iSliceSize[P_SLICE] +pCtx->sStatData[i][j].sSliceData.iSliceSize[B_SLICE] ) / (float)(iCount+pCtx->pWelsSvcRc[i].iSkipFrameNum)/1000, | |
| 2328 | − 1.0f * pCtx->pSvcParam->sDependencyLayers[i].fOutputFrameRate ); | |
| 2329 | − | |
| 2330 | − } | |
| 2331 | − | |
| 2332 | − } | |
| 2333 | − | |
| 2334 | − } | |
| 2335 | −} | |
| 2336 | −#endif | |
| 2337 | −/*! | |
| 2338 | − * \brief uninitialize Wels encoder core library | |
| 2339 | − * \pParam pEncCtx sWelsEncCtx* | |
| 2340 | − * \return none | |
| 2341 | − */ | |
| 2342 | −void WelsUninitEncoderExt( sWelsEncCtx **ppCtx ) | |
| 2343 | −{ | |
| 2344 | − if ( NULL == ppCtx || NULL == *ppCtx ) | |
| 2345 | − return; | |
| 2346 | − | |
| 2347 | − WelsLog( *ppCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), pCtx= %p, iThreadCount= %d, iMultipleThreadIdc= %d.\n", (void *)(*ppCtx), (*ppCtx)->pSvcParam->iCountThreadsNum, (*ppCtx)->pSvcParam->iMultipleThreadIdc ); | |
| 2348 | − | |
| 2349 | −#if defined(STAT_OUTPUT) | |
| 2350 | − StatOverallEncodingExt( *ppCtx ); | |
| 2351 | −#endif | |
| 2352 | − | |
| 2353 | −#if defined(MT_ENABLED) | |
| 2354 | − if ( (*ppCtx)->pSvcParam->iMultipleThreadIdc > 1 && (*ppCtx)->pSliceThreading != NULL ) | |
| 2355 | − { | |
| 2356 | − const int32_t iThreadCount = (*ppCtx)->pSvcParam->iCountThreadsNum; | |
| 2357 | − int32_t iThreadIdx = 0; | |
| 2358 | − | |
| 2359 | −#if defined(WIN32) | |
| 2360 | − if ( (*ppCtx)->pSliceThreading->pExitEncodeEvent != NULL ) | |
| 2361 | − { | |
| 2362 | − do { | |
| 2363 | − if ( (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] != NULL ) // iThreadIdx is already created successfully | |
| 2364 | − WelsEventSignal( &(*ppCtx)->pSliceThreading->pExitEncodeEvent[iThreadIdx] ); | |
| 2365 | − ++ iThreadIdx; | |
| 2366 | − } while(iThreadIdx < iThreadCount); | |
| 2367 | − | |
| 2368 | − WelsMultipleEventsWaitAllBlocking( iThreadCount, &(*ppCtx)->pSliceThreading->pFinSliceCodingEvent[0] ); | |
| 2369 | − | |
| 2370 | − } | |
| 2371 | −#elif defined(__GNUC__) | |
| 2372 | − while ( iThreadIdx < iThreadCount ) | |
| 2373 | − { | |
| 2374 | − int res = 0; | |
| 2375 | − if ( (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] ) | |
| 2376 | − { | |
| 2377 | − res = WelsThreadCancel( (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] ); | |
| 2378 | − WelsLog( *ppCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), WelsThreadCancel(pThreadHandles%d) return %d..\n", iThreadIdx, res); | |
| 2379 | − res = WelsThreadJoin( (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] ); // waiting thread exit | |
| 2380 | − WelsLog( *ppCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), pthread_join(pThreadHandles%d) return %d..\n", iThreadIdx, res); | |
| 2381 | − (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] = 0; | |
| 2382 | − } | |
| 2383 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 2384 | − if ( (*ppCtx)->pSliceThreading->pUpdateMbListThrdHandles[iThreadIdx] ) | |
| 2385 | − { | |
| 2386 | − res = WelsThreadCancel( (*ppCtx)->pSliceThreading->pUpdateMbListThrdHandles[iThreadIdx] ); | |
| 2387 | − WelsLog( *ppCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), WelsThreadCancel(pUpdateMbListThrdHandles%d) return %d..\n", iThreadIdx, res); | |
| 2388 | − res = WelsThreadJoin( (*ppCtx)->pSliceThreading->pUpdateMbListThrdHandles[iThreadIdx] ); // waiting thread exit | |
| 2389 | − WelsLog( *ppCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), pthread_join(pUpdateMbListThrdHandles%d) return %d..\n", iThreadIdx, res); | |
| 2390 | − (*ppCtx)->pSliceThreading->pUpdateMbListThrdHandles[iThreadIdx] = 0; | |
| 2391 | − } | |
| 2392 | −#endif//DYNAMIC_SLICE_ASSIGN && TRY_SLICING_BALANCE | |
| 2393 | − ++ iThreadIdx; | |
| 2394 | − } | |
| 2395 | −#endif//WIN32 | |
| 2396 | − } | |
| 2397 | −#endif//MT_ENABLED | |
| 2398 | − | |
| 2399 | − if ((*ppCtx)->pVpp) | |
| 2400 | − { | |
| 2401 | − delete (*ppCtx)->pVpp; | |
| 2402 | − (*ppCtx)->pVpp = NULL; | |
| 2403 | − } | |
| 2404 | − FreeMemorySvc( ppCtx ); | |
| 2405 | − *ppCtx = NULL; | |
| 2406 | −} | |
| 2407 | − | |
| 2408 | −/*! | |
| 2409 | − * \brief get temporal level due to configuration and coding context | |
| 2410 | − */ | |
| 2411 | −static inline int32_t GetTemporalLevel( SDLayerParam *fDlp, const int32_t kiFrameNum, const int32_t kiGopSize ) | |
| 2412 | −{ | |
| 2413 | − const int32_t kiCodingIdx = kiFrameNum & (kiGopSize-1); | |
| 2414 | − | |
| 2415 | − return fDlp->uiCodingIdx2TemporalId[kiCodingIdx]; | |
| 2416 | −} | |
| 2417 | − | |
| 2418 | −void DynslcUpdateMbNeighbourInfoListForAllSlices( SSliceCtx *pSliceCtx, SMB *pMbList ) | |
| 2419 | −{ | |
| 2420 | − const int32_t kiMbWidth = pSliceCtx->iMbWidth; | |
| 2421 | − const int32_t kiEndMbInSlice = pSliceCtx->iMbNumInFrame - 1; | |
| 2422 | − int32_t iIdx = 0; | |
| 2423 | − | |
| 2424 | − do { | |
| 2425 | − SMB *pMb = &pMbList[iIdx]; | |
| 2426 | − uint32_t uiNeighborAvailFlag = 0; | |
| 2427 | − const int32_t kiMbXY = pMb->iMbXY; | |
| 2428 | − const int32_t kiMbX = pMb->iMbX; | |
| 2429 | − const int32_t kiMbY = pMb->iMbY; | |
| 2430 | − BOOL_T bLeft; | |
| 2431 | − BOOL_T bTop; | |
| 2432 | − BOOL_T bLeftTop; | |
| 2433 | − BOOL_T bRightTop; | |
| 2434 | − int32_t uiSliceIdc; | |
| 2435 | − int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY; | |
| 2436 | − | |
| 2437 | − uiSliceIdc = WelsMbToSliceIdc(pSliceCtx, kiMbXY); | |
| 2438 | − pMb->uiSliceIdc = uiSliceIdc; | |
| 2439 | − iLeftXY = kiMbXY - 1; | |
| 2440 | − iTopXY = kiMbXY - kiMbWidth; | |
| 2441 | − iLeftTopXY = iTopXY - 1; | |
| 2442 | − iRightTopXY = iTopXY + 1; | |
| 2443 | − | |
| 2444 | − bLeft = (kiMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iLeftXY)); | |
| 2445 | − bTop = (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iTopXY)); | |
| 2446 | − bLeftTop = (kiMbX > 0) && (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iLeftTopXY)); | |
| 2447 | − bRightTop = (kiMbX < (kiMbWidth-1)) && (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iRightTopXY)); | |
| 2448 | − | |
| 2449 | − if( bLeft ){ | |
| 2450 | − uiNeighborAvailFlag |= LEFT_MB_POS; | |
| 2451 | − } | |
| 2452 | − if( bTop ){ | |
| 2453 | − uiNeighborAvailFlag |= TOP_MB_POS; | |
| 2454 | − } | |
| 2455 | − if( bLeftTop ){ | |
| 2456 | − uiNeighborAvailFlag |= TOPLEFT_MB_POS; | |
| 2457 | − } | |
| 2458 | − if( bRightTop ){ | |
| 2459 | − uiNeighborAvailFlag |= TOPRIGHT_MB_POS; | |
| 2460 | − } | |
| 2461 | − pMb->uiNeighborAvail = (uint8_t)uiNeighborAvailFlag; | |
| 2462 | − | |
| 2463 | − ++ iIdx; | |
| 2464 | − } while(iIdx <= kiEndMbInSlice); | |
| 2465 | −} | |
| 2466 | − | |
| 2467 | −/* | |
| 2468 | − * TUNE back if number of picture partition decision algorithm based on past if available | |
| 2469 | − */ | |
| 2470 | −int32_t PicPartitionNumDecision( sWelsEncCtx *pCtx ) | |
| 2471 | −{ | |
| 2472 | − int32_t iPartitionNum = 1; | |
| 2473 | −#ifdef MT_ENABLED | |
| 2474 | − if ( pCtx->pSvcParam->iMultipleThreadIdc > 1 ) | |
| 2475 | − { | |
| 2476 | − iPartitionNum = pCtx->pSvcParam->iCountThreadsNum; | |
| 2477 | −#if !defined(FIXED_PARTITION_ASSIGN) | |
| 2478 | − if ( P_SLICE == pCtx->eSliceType ) | |
| 2479 | − iPartitionNum = 1; | |
| 2480 | −#endif//!FIXED_PARTITION_ASSIGN | |
| 2481 | − } | |
| 2482 | − return iPartitionNum; | |
| 2483 | −#else | |
| 2484 | − return iPartitionNum; | |
| 2485 | −#endif//MT_ENABLED | |
| 2486 | −} | |
| 2487 | − | |
| 2488 | −#if defined(MT_ENABLED) | |
| 2489 | −void WelsInitCurrentQBLayerMltslc( sWelsEncCtx *pCtx ) | |
| 2490 | −{ | |
| 2491 | − //pData init | |
| 2492 | − SDqLayer* pCurDq = pCtx->pCurDqLayer; | |
| 2493 | − SSliceCtx* pSliceCtx = (pCurDq->pSliceEncCtx); | |
| 2494 | − | |
| 2495 | − //mb_neighbor | |
| 2496 | − DynslcUpdateMbNeighbourInfoListForAllSlices( pSliceCtx, pCurDq->sMbDataP ); | |
| 2497 | −} | |
| 2498 | − | |
| 2499 | −void UpdateSlicepEncCtxWithPartition( SSliceCtx *pSliceCtx, int32_t iPartitionNum ) | |
| 2500 | −{ | |
| 2501 | − const int32_t kiMbNumInFrame = pSliceCtx->iMbNumInFrame; | |
| 2502 | − int32_t iCountMbNumPerPartition = kiMbNumInFrame; | |
| 2503 | − int32_t iAssignableMbLeft = kiMbNumInFrame; | |
| 2504 | − int32_t iFirstMbIdx = 0; | |
| 2505 | − int32_t i/*, j*/; | |
| 2506 | − | |
| 2507 | − if ( iPartitionNum <= 0 ) | |
| 2508 | − iPartitionNum = 1; | |
| 2509 | − else if ( iPartitionNum > AVERSLICENUM_CONSTRAINT ) | |
| 2510 | − iPartitionNum = AVERSLICENUM_CONSTRAINT; // AVERSLICENUM_CONSTRAINT might be variable, however not fixed by MACRO | |
| 2511 | − iCountMbNumPerPartition /= iPartitionNum; | |
| 2512 | − pSliceCtx->iSliceNumInFrame = iPartitionNum; | |
| 2513 | − i = 0; | |
| 2514 | − while( i < iPartitionNum ) | |
| 2515 | − { | |
| 2516 | − if ( i + 1 == iPartitionNum ) | |
| 2517 | − { | |
| 2518 | − pSliceCtx->pCountMbNumInSlice[i] = iAssignableMbLeft; | |
| 2519 | − } | |
| 2520 | − else | |
| 2521 | − { | |
| 2522 | − pSliceCtx->pCountMbNumInSlice[i] = iCountMbNumPerPartition; | |
| 2523 | − } | |
| 2524 | − pSliceCtx->pFirstMbInSlice[i] = iFirstMbIdx; | |
| 2525 | − | |
| 2526 | − memset( pSliceCtx->pOverallMbMap+iFirstMbIdx, (uint8_t)i, pSliceCtx->pCountMbNumInSlice[i]*sizeof(uint8_t) ); | |
| 2527 | − | |
| 2528 | − // for next partition(or pSlice) | |
| 2529 | − iFirstMbIdx += pSliceCtx->pCountMbNumInSlice[i]; | |
| 2530 | − iAssignableMbLeft -= pSliceCtx->pCountMbNumInSlice[i]; | |
| 2531 | − ++ i; | |
| 2532 | − } | |
| 2533 | −} | |
| 2534 | − | |
| 2535 | −void WelsInitCurrentDlayerMltslc( sWelsEncCtx *pCtx, int32_t iPartitionNum ) | |
| 2536 | −{ | |
| 2537 | − SDqLayer* pCurDq = pCtx->pCurDqLayer; | |
| 2538 | − SSliceCtx* pSliceCtx = pCurDq->pSliceEncCtx; | |
| 2539 | − | |
| 2540 | − UpdateSlicepEncCtxWithPartition( pSliceCtx, iPartitionNum ); | |
| 2541 | − | |
| 2542 | − if ( I_SLICE == pCtx->eSliceType )//check if uiSliceSizeConstraint too small | |
| 2543 | − { | |
| 2544 | −#define byte_complexIMBat26 (60) | |
| 2545 | − uint8_t iCurDid = pCtx->uiDependencyId; | |
| 2546 | − uint32_t uiFrmByte = 0; | |
| 2547 | − | |
| 2548 | − if ( pCtx->pSvcParam->bEnableRc ) | |
| 2549 | − {//RC case | |
| 2550 | − uiFrmByte = ( | |
| 2551 | − ( (uint32_t)(pCtx->pSvcParam->sDependencyLayers[iCurDid].iSpatialBitrate) | |
| 2552 | − /(uint32_t)(pCtx->pSvcParam->sDependencyLayers[iCurDid].fInputFrameRate) ) >> 3 ); | |
| 2553 | − } | |
| 2554 | − else | |
| 2555 | − {//fixed QP case | |
| 2556 | − const int32_t iTtlMbNumInFrame = pSliceCtx->iMbNumInFrame; | |
| 2557 | − int32_t iQDeltaTo26 = ( 26 - pCtx->pSvcParam->sDependencyLayers[iCurDid].iDLayerQp ); | |
| 2558 | − | |
| 2559 | − uiFrmByte = (iTtlMbNumInFrame * byte_complexIMBat26); | |
| 2560 | − if ( iQDeltaTo26 > 0 ) | |
| 2561 | − { | |
| 2562 | − //smaller QP than 26 | |
| 2563 | − uiFrmByte = (uint32_t)( uiFrmByte * ( (float)iQDeltaTo26 / 4 ) ); | |
| 2564 | − } | |
| 2565 | − else if ( iQDeltaTo26 < 0 ) | |
| 2566 | − { | |
| 2567 | − //larger QP than 26 | |
| 2568 | − iQDeltaTo26 = ( (-iQDeltaTo26) >> 2 ); //delta mod 4 | |
| 2569 | − uiFrmByte = ( uiFrmByte >> (iQDeltaTo26) ); //if delta 4, byte /2 | |
| 2570 | − } | |
| 2571 | − } | |
| 2572 | − | |
| 2573 | − //MINPACKETSIZE_CONSTRAINT | |
| 2574 | − if ( pSliceCtx->uiSliceSizeConstraint | |
| 2575 | − < | |
| 2576 | − (uint32_t)( uiFrmByte//suppose 16 byte per mb at average | |
| 2577 | − / ( pSliceCtx->iMaxSliceNumConstraint ) ) | |
| 2578 | − ) | |
| 2579 | − { | |
| 2580 | − | |
| 2581 | − WelsLog( pCtx, | |
| 2582 | − WELS_LOG_WARNING, | |
| 2583 | − "Set-SliceConstraint(%d) too small for current resolution (MB# %d) under QP/BR!\n", | |
| 2584 | − pSliceCtx->uiSliceSizeConstraint, | |
| 2585 | − pSliceCtx->iMbNumInFrame | |
| 2586 | − ); | |
| 2587 | − } | |
| 2588 | − } | |
| 2589 | − | |
| 2590 | − WelsInitCurrentQBLayerMltslc( pCtx ); | |
| 2591 | −} | |
| 2592 | −#else | |
| 2593 | −void WelsInitCurrentQBLayerMltslc( sWelsEncCtx *pCtx ) | |
| 2594 | −{ | |
| 2595 | − //pData init | |
| 2596 | − SDqLayer* pCurDq = pCtx->pCurDqLayer; | |
| 2597 | − SSliceCtx* pSliceCtx = (pCurDq->pSliceEncCtx); | |
| 2598 | − SSlice * pSlice = &pCurDq->sLayerInfo.pSliceInLayer[0]; | |
| 2599 | − int32_t iTtlMbNumInFrame = pSliceCtx->iMbNumInFrame; | |
| 2600 | − | |
| 2601 | − //pSliceCtx | |
| 2602 | − memset( pSliceCtx->pOverallMbMap, 0, iTtlMbNumInFrame * sizeof(uint8_t) ); | |
| 2603 | − memset( pSliceCtx->pCountMbNumInSlice, 0, pSliceCtx->iSliceNumInFrame * sizeof(int32_t) ); | |
| 2604 | − memset( pSliceCtx->pFirstMbInSlice, 0, pSliceCtx->iSliceNumInFrame * sizeof(int16_t) ); | |
| 2605 | − pSliceCtx->iSliceNumInFrame = 1;// | |
| 2606 | − pSliceCtx->pCountMbNumInSlice[0] = iTtlMbNumInFrame; | |
| 2607 | − | |
| 2608 | − //mb_neighbor | |
| 2609 | − DynslcUpdateMbNeighbourInfoListForAllSlices( pSliceCtx, pCurDq->sMbDataP ); | |
| 2610 | − | |
| 2611 | − //pSlice init | |
| 2612 | − pSlice->uiSliceIdx = 0; | |
| 2613 | − pSlice->pSliceBsa = &pCtx->pOut->sBsWrite; | |
| 2614 | − pSlice->bDynamicSlicingSliceSizeCtrlFlag = false; | |
| 2615 | − pSlice->uiAssumeLog2BytePerMb = ( pCtx->eSliceType == P_SLICE ) ? 0 : 1; | |
| 2616 | −} | |
| 2617 | − | |
| 2618 | −void WelsInitCurrentDlayerMltslc( sWelsEncCtx *pCtx, int32_t iPartitionNum ) | |
| 2619 | −{ | |
| 2620 | − SDqLayer* pCurDq = pCtx->pCurDqLayer; | |
| 2621 | − SSliceCtx* pSliceCtx = ( pCurDq->pSliceEncCtx ); | |
| 2622 | − int32_t iTtlMbNumInFrame = pCurDq->iMbHeight*pCurDq->iMbWidth; | |
| 2623 | − | |
| 2624 | − pSliceCtx->iMbNumInFrame | |
| 2625 | − = pSliceCtx->pCountMbNumInSlice[0] = iTtlMbNumInFrame; | |
| 2626 | − | |
| 2627 | − if ( I_SLICE == pCtx->eSliceType )//check if uiSliceSizeConstraint too small | |
| 2628 | − { | |
| 2629 | −#define byte_complexIMBat26 (60) | |
| 2630 | − uint8_t iCurDid = pCtx->uiDependencyId; | |
| 2631 | − uint32_t uiFrmByte = 0; | |
| 2632 | − | |
| 2633 | − if ( pCtx->pSvcParam->bEnableRc ) | |
| 2634 | − {//RC case | |
| 2635 | − uiFrmByte = ( | |
| 2636 | − ( (uint32_t)(pCtx->pSvcParam->sDependencyLayers[iCurDid].iSpatialBitrate) | |
| 2637 | − /(uint32_t)(pCtx->pSvcParam->sDependencyLayers[iCurDid].fInputFrameRate) ) >> 3 ); | |
| 2638 | − } | |
| 2639 | − else | |
| 2640 | − {//fixed QP case | |
| 2641 | − int32_t iQDeltaTo26 = ( 26 - pCtx->pSvcParam->sDependencyLayers[iCurDid].iDLayerQp ); | |
| 2642 | − | |
| 2643 | − uiFrmByte = (iTtlMbNumInFrame * byte_complexIMBat26); | |
| 2644 | − if ( iQDeltaTo26 > 0 ) | |
| 2645 | − { | |
| 2646 | − //smaller QP than 26 | |
| 2647 | − uiFrmByte = (uint32_t)( uiFrmByte * ( (float)iQDeltaTo26 / 4 ) ); | |
| 2648 | − } | |
| 2649 | − else if ( iQDeltaTo26 < 0 ) | |
| 2650 | − { | |
| 2651 | − //larger QP than 26 | |
| 2652 | − iQDeltaTo26 = ( (-iQDeltaTo26) >> 2 ); //delta mod 4 | |
| 2653 | − uiFrmByte = ( uiFrmByte >> (iQDeltaTo26) ); //if delta 4, byte /2 | |
| 2654 | − } | |
| 2655 | − } | |
| 2656 | − | |
| 2657 | − //MINPACKETSIZE_CONSTRAINT | |
| 2658 | − if ( pSliceCtx->uiSliceSizeConstraint | |
| 2659 | − < | |
| 2660 | − (uint32_t)( uiFrmByte//suppose 16 byte per mb at average | |
| 2661 | − / ( pSliceCtx->iMaxSliceNumConstraint ) ) | |
| 2662 | − ) | |
| 2663 | − { | |
| 2664 | − | |
| 2665 | − WelsLog( pCtx, | |
| 2666 | − WELS_LOG_WARNING, | |
| 2667 | − "Set-SliceConstraint(%d) too small for current resolution (MB# %d) under QP/BR!\n", | |
| 2668 | − pSliceCtx->uiSliceSizeConstraint, | |
| 2669 | − pSliceCtx->iMbNumInFrame | |
| 2670 | − ); | |
| 2671 | − } | |
| 2672 | − } | |
| 2673 | − | |
| 2674 | − WelsInitCurrentQBLayerMltslc( pCtx ); | |
| 2675 | −} | |
| 2676 | −#endif | |
| 2677 | − | |
| 2678 | −/*! | |
| 2679 | − * \brief initialize current layer | |
| 2680 | − */ | |
| 2681 | −void WelsInitCurrentLayer( sWelsEncCtx *pCtx, | |
| 2682 | − const int32_t kiWidth, | |
| 2683 | − const int32_t kiHeight ) | |
| 2684 | −{ | |
| 2685 | − SWelsSvcCodingParam *pParam = pCtx->pSvcParam; | |
| 2686 | − SPicture *pEncPic = pCtx->pEncPic; | |
| 2687 | − SPicture *pDecPic = pCtx->pDecPic; | |
| 2688 | − SDqLayer *pCurDq = pCtx->pCurDqLayer; | |
| 2689 | − SSlice *pBaseSlice = &pCurDq->sLayerInfo.pSliceInLayer[0]; | |
| 2690 | − SSlice *pSlice = NULL; | |
| 2691 | − const uint8_t kiCurDid = pCtx->uiDependencyId; | |
| 2692 | − const bool_t kbUseSubsetSpsFlag= (kiCurDid > BASE_DEPENDENCY_ID); | |
| 2693 | − SDLayerParam *fDlp = &pParam->sDependencyLayers[kiCurDid]; | |
| 2694 | − SNalUnitHeaderExt *pNalHdExt = &pCurDq->sLayerInfo.sNalHeaderExt; | |
| 2695 | − SNalUnitHeader *pNalHd = &pNalHdExt->sNalHeader; | |
| 2696 | − SDqIdc *pDqIdc = &pCtx->pDqIdcMap[kiCurDid]; | |
| 2697 | − int32_t iIdx = 0; | |
| 2698 | − int32_t iSliceCount = 0; | |
| 2699 | − | |
| 2700 | − if ( NULL == pCurDq ) | |
| 2701 | − return; | |
| 2702 | − | |
| 2703 | − pCurDq->pDecPic = pDecPic; | |
| 2704 | − | |
| 2705 | − if ( fDlp->sMso.uiSliceMode == SM_DYN_SLICE ) // need get extra slices for update | |
| 2706 | − iSliceCount = GetInitialSliceNum( pCurDq->iMbWidth, pCurDq->iMbHeight, &fDlp->sMso ); | |
| 2707 | − else | |
| 2708 | − iSliceCount = GetCurrentSliceNum( pCurDq->pSliceEncCtx ); | |
| 2709 | − assert( iSliceCount > 0 ); | |
| 2710 | − | |
| 2711 | − pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId = pDqIdc->iPpsId; | |
| 2712 | − pCurDq->sLayerInfo.pPpsP = | |
| 2713 | − pBaseSlice->sSliceHeaderExt.sSliceHeader.pPps = &pCtx->pPPSArray[pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId]; | |
| 2714 | − pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId = pDqIdc->iSpsId; | |
| 2715 | − if ( kbUseSubsetSpsFlag ) | |
| 2716 | − { | |
| 2717 | − pCurDq->sLayerInfo.pSubsetSpsP = &pCtx->pSubsetArray[pDqIdc->iSpsId]; | |
| 2718 | − pCurDq->sLayerInfo.pSpsP = | |
| 2719 | − pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCurDq->sLayerInfo.pSubsetSpsP->pSps; | |
| 2720 | − } | |
| 2721 | − else | |
| 2722 | − { | |
| 2723 | − pCurDq->sLayerInfo.pSubsetSpsP = NULL; | |
| 2724 | − pCurDq->sLayerInfo.pSpsP = | |
| 2725 | − pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCtx->pSpsArray[pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId]; | |
| 2726 | − } | |
| 2727 | − | |
| 2728 | − pSlice = pBaseSlice; | |
| 2729 | − iIdx = 1; | |
| 2730 | − while ( iIdx < iSliceCount ) { | |
| 2731 | − ++ pSlice; | |
| 2732 | − pSlice->sSliceHeaderExt.sSliceHeader.iPpsId = pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId; | |
| 2733 | − pSlice->sSliceHeaderExt.sSliceHeader.pPps = pBaseSlice->sSliceHeaderExt.sSliceHeader.pPps; | |
| 2734 | − pSlice->sSliceHeaderExt.sSliceHeader.iSpsId = pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId; | |
| 2735 | − pSlice->sSliceHeaderExt.sSliceHeader.pSps = pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps; | |
| 2736 | − ++ iIdx; | |
| 2737 | − } | |
| 2738 | − | |
| 2739 | − memset( pNalHdExt, 0, sizeof(SNalUnitHeaderExt) ); | |
| 2740 | − pNalHd->uiNalRefIdc = pCtx->eNalPriority; | |
| 2741 | − pNalHd->eNalUnitType = pCtx->eNalType; | |
| 2742 | − | |
| 2743 | − pNalHdExt->uiDependencyId = kiCurDid; | |
| 2744 | − pNalHdExt->bDiscardableFlag = (pCtx->bNeedPrefixNalFlag) ? (pNalHd->uiNalRefIdc == NRI_PRI_LOWEST) : false; | |
| 2745 | − pNalHdExt->bIdrFlag = (pCtx->iFrameNum == 0) && ((pCtx->eNalType == NAL_UNIT_CODED_SLICE_IDR) || (pCtx->eSliceType == I_SLICE)); | |
| 2746 | − pNalHdExt->uiTemporalId = pCtx->uiTemporalId; | |
| 2747 | − | |
| 2748 | − pBaseSlice->bSliceHeaderExtFlag = (NAL_UNIT_CODED_SLICE_EXT == pNalHd->eNalUnitType); | |
| 2749 | − | |
| 2750 | − pSlice = pBaseSlice; | |
| 2751 | − iIdx = 1; | |
| 2752 | − while (iIdx < iSliceCount) { | |
| 2753 | − ++ pSlice; | |
| 2754 | − pSlice->bSliceHeaderExtFlag = pBaseSlice->bSliceHeaderExtFlag; | |
| 2755 | − ++ iIdx; | |
| 2756 | − } | |
| 2757 | − | |
| 2758 | − // pEncPic pData | |
| 2759 | − pCurDq->pEncData[0] = pEncPic->pData[0]; | |
| 2760 | − pCurDq->pEncData[1] = pEncPic->pData[1]; | |
| 2761 | − pCurDq->pEncData[2] = pEncPic->pData[2]; | |
| 2762 | − pCurDq->iEncStride[0] = pEncPic->iLineSize[0]; | |
| 2763 | − pCurDq->iEncStride[1] = pEncPic->iLineSize[1]; | |
| 2764 | − pCurDq->iEncStride[2] = pEncPic->iLineSize[2]; | |
| 2765 | − // cs pData | |
| 2766 | − pCurDq->pCsData[0] = pDecPic->pData[0]; | |
| 2767 | − pCurDq->pCsData[1] = pDecPic->pData[1]; | |
| 2768 | − pCurDq->pCsData[2] = pDecPic->pData[2]; | |
| 2769 | − pCurDq->iCsStride[0] = pDecPic->iLineSize[0]; | |
| 2770 | − pCurDq->iCsStride[1] = pDecPic->iLineSize[1]; | |
| 2771 | − pCurDq->iCsStride[2] = pDecPic->iLineSize[2]; | |
| 2772 | − | |
| 2773 | − if ( pCurDq->pRefLayer != NULL ) | |
| 2774 | − { | |
| 2775 | − pCurDq->bBaseLayerAvailableFlag = true; | |
| 2776 | − } | |
| 2777 | − else | |
| 2778 | − { | |
| 2779 | − pCurDq->bBaseLayerAvailableFlag = false; | |
| 2780 | − } | |
| 2781 | −} | |
| 2782 | − | |
| 2783 | −void PreprocessSliceCoding( sWelsEncCtx *pCtx ) | |
| 2784 | −{ | |
| 2785 | − SDqLayer *pCurLayer = pCtx->pCurDqLayer; | |
| 2786 | − const bool_t kbBaseAvail = pCurLayer->bBaseLayerAvailableFlag; | |
| 2787 | − | |
| 2788 | − /* function pointers conditional assignment under sWelsEncCtx, layer_mb_enc_rec (in stack) is exclusive */ | |
| 2789 | − | |
| 2790 | − if ( P_SLICE == pCtx->eSliceType ) | |
| 2791 | − { | |
| 2792 | − if ( kbBaseAvail ) | |
| 2793 | − { | |
| 2794 | − if ( pCtx->pSvcParam->iNumDependencyLayer == (pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId + 1) ) // | |
| 2795 | − { | |
| 2796 | − pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSad; | |
| 2797 | − pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode; | |
| 2798 | − pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartitionVaa; | |
| 2799 | − pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaa; | |
| 2800 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Sad; | |
| 2801 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Sad; | |
| 2802 | − pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSad; | |
| 2803 | − } | |
| 2804 | − else | |
| 2805 | − { | |
| 2806 | − pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSatd; | |
| 2807 | − pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode; | |
| 2808 | − pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartition; | |
| 2809 | − pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartition; | |
| 2810 | − pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd; | |
| 2811 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Satd; | |
| 2812 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Satd; | |
| 2813 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3Satd; | |
| 2814 | − } | |
| 2815 | − pCtx->pFuncList->sSampleDealingFuncs.pfMeCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd; | |
| 2816 | − } | |
| 2817 | − else | |
| 2818 | − { | |
| 2819 | − //case 3: pBase layer MD + encoding | |
| 2820 | − if ( pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId+1 == pCtx->pSvcParam->iNumDependencyLayer ) | |
| 2821 | − { | |
| 2822 | − pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSad; | |
| 2823 | − pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode; | |
| 2824 | − pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartitionVaa; | |
| 2825 | − pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaa; | |
| 2826 | − pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSad; | |
| 2827 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Sad; | |
| 2828 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Sad; | |
| 2829 | − } | |
| 2830 | − else | |
| 2831 | − { | |
| 2832 | − pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSatd; | |
| 2833 | − pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode; | |
| 2834 | − pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartition; | |
| 2835 | − pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartition; | |
| 2836 | − pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd; | |
| 2837 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Satd; | |
| 2838 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Satd; | |
| 2839 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3Satd; | |
| 2840 | − } | |
| 2841 | − pCtx->pFuncList->sSampleDealingFuncs.pfMeCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd; | |
| 2842 | − } | |
| 2843 | − } | |
| 2844 | − else if ( I_SLICE == pCtx->eSliceType ) | |
| 2845 | − { | |
| 2846 | − if ( pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId+1 == pCtx->pSvcParam->iNumDependencyLayer ) | |
| 2847 | − { | |
| 2848 | − pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSad; | |
| 2849 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Sad; | |
| 2850 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Sad; | |
| 2851 | − pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartitionVaa; | |
| 2852 | − } | |
| 2853 | − else | |
| 2854 | − { | |
| 2855 | − pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd; | |
| 2856 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Satd; | |
| 2857 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Satd; | |
| 2858 | − pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3Satd; | |
| 2859 | − pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartition; | |
| 2860 | − } | |
| 2861 | − } | |
| 2862 | −} | |
| 2863 | − | |
| 2864 | −/*! | |
| 2865 | − * \brief swap pDq layers between current pDq layer and reference pDq layer | |
| 2866 | − */ | |
| 2867 | − | |
| 2868 | −static inline void WelsSwapDqLayers( sWelsEncCtx *pCtx ) | |
| 2869 | −{ | |
| 2870 | − // swap and assign reference | |
| 2871 | − const int32_t kiDid = pCtx->uiDependencyId; | |
| 2872 | − const int32_t kiNextDqIdx = 1 + kiDid; | |
| 2873 | − | |
| 2874 | − SDqLayer *pTmpLayer = pCtx->ppDqLayerList[kiNextDqIdx]; | |
| 2875 | − SDqLayer *pRefLayer = pCtx->pCurDqLayer; | |
| 2876 | − pCtx->pCurDqLayer = pTmpLayer; | |
| 2877 | − pCtx->pCurDqLayer->pRefLayer = pRefLayer; | |
| 2878 | −} | |
| 2879 | − | |
| 2880 | −/*! | |
| 2881 | − * \brief prefetch reference picture after WelsBuildRefList | |
| 2882 | − */ | |
| 2883 | −static inline void PrefetchReferencePicture( sWelsEncCtx *pCtx, const EFrameType keFrameType ) | |
| 2884 | −{ | |
| 2885 | − SSlice *pSliceBase = &pCtx->pCurDqLayer->sLayerInfo.pSliceInLayer[0]; | |
| 2886 | − const int32_t kiSliceCount = GetCurrentSliceNum( pCtx->pCurDqLayer->pSliceEncCtx ); | |
| 2887 | − int32_t iIdx = 0; | |
| 2888 | − uint8_t uiRefIdx = -1; | |
| 2889 | − | |
| 2890 | − assert( kiSliceCount > 0 ); | |
| 2891 | − if ( keFrameType != WELS_FRAME_TYPE_IDR ) | |
| 2892 | − { | |
| 2893 | − assert( pCtx->iNumRef0 > 0 ); | |
| 2894 | − pCtx->pRefPic = pCtx->pRefList0[0]; // always get item 0 due to reordering done | |
| 2895 | − pCtx->pCurDqLayer->pRefPic = pCtx->pRefPic; | |
| 2896 | − uiRefIdx = 0; // reordered reference iIndex | |
| 2897 | − } | |
| 2898 | − else // safe for IDR coding | |
| 2899 | − { | |
| 2900 | − pCtx->pRefPic = NULL; | |
| 2901 | − pCtx->pCurDqLayer->pRefPic = NULL; | |
| 2902 | − } | |
| 2903 | − | |
| 2904 | − iIdx = 0; | |
| 2905 | − while (iIdx < kiSliceCount) { | |
| 2906 | − pSliceBase->sSliceHeaderExt.sSliceHeader.uiRefIndex = uiRefIdx; | |
| 2907 | − ++ pSliceBase; | |
| 2908 | − ++ iIdx; | |
| 2909 | − } | |
| 2910 | −} | |
| 2911 | − | |
| 2912 | − | |
| 2913 | −void ParasetIdAdditionIdAdjust( SParaSetOffsetVariable *sParaSetOffsetVariable, const int32_t kiCurEncoderParaSetId, const uint32_t kuiMaxIdInBs )//paraset_type = 0: SPS; =1: PPS | |
| 2914 | −{ | |
| 2915 | − //SPS_ID in avc_sps and pSubsetSps will be different using this | |
| 2916 | − //SPS_ID case example: | |
| 2917 | − //1st enter: next_spsid_in_bs == 0; spsid == 0; delta==0; //actual spsid_in_bs == 0 | |
| 2918 | − //1st finish: next_spsid_in_bs == 1; | |
| 2919 | − //2nd enter: next_spsid_in_bs == 1; spsid == 0; delta==1; //actual spsid_in_bs == 1 | |
| 2920 | − //2nd finish: next_spsid_in_bs == 2; | |
| 2921 | − //31st enter: next_spsid_in_bs == 31; spsid == 0~2; delta==31~29; //actual spsid_in_bs == 31 | |
| 2922 | − //31st finish: next_spsid_in_bs == 0; | |
| 2923 | − //31st enter: next_spsid_in_bs == 0; spsid == 0~2; delta==-2~0; //actual spsid_in_bs == 0 | |
| 2924 | − //31st finish: next_spsid_in_bs == 1; | |
| 2925 | − | |
| 2926 | − const int32_t kiEncId = kiCurEncoderParaSetId; | |
| 2927 | − const uint32_t kuiPrevIdInBs = sParaSetOffsetVariable->iParaSetIdDelta[kiEncId] + kiEncId;//mark current_id | |
| 2928 | − const bool_t *kpUsedIdPointer = &sParaSetOffsetVariable->bUsedParaSetIdInBs[0]; | |
| 2929 | − uint32_t uiNextIdInBs = sParaSetOffsetVariable->uiNextParaSetIdToUseInBs; | |
| 2930 | − | |
| 2931 | −#if _DEBUG | |
| 2932 | − if ( 0 != sParaSetOffsetVariable->iParaSetIdDelta[kiEncId] ) | |
| 2933 | − assert ( sParaSetOffsetVariable->bUsedParaSetIdInBs[kuiPrevIdInBs] ); //sure the prev-used one was marked activated correctly | |
| 2934 | −#endif | |
| 2935 | − //update current layer's pCodingParam | |
| 2936 | − sParaSetOffsetVariable->iParaSetIdDelta[kiEncId] = uiNextIdInBs - kiEncId; //for current parameter set, change its id_delta | |
| 2937 | − //write pso pData for next update: | |
| 2938 | − sParaSetOffsetVariable->bUsedParaSetIdInBs[kuiPrevIdInBs] = false; // | |
| 2939 | − sParaSetOffsetVariable->bUsedParaSetIdInBs[uiNextIdInBs] = true; // update current used_id | |
| 2940 | − | |
| 2941 | − //prepare for next update: | |
| 2942 | − // find the next avaibable iId | |
| 2943 | − do | |
| 2944 | − { | |
| 2945 | − ++uiNextIdInBs; | |
| 2946 | − if (uiNextIdInBs >= kuiMaxIdInBs ) | |
| 2947 | − { | |
| 2948 | − uiNextIdInBs = 0;//ensure the SPS_ID wound not exceed MAX_SPS_COUNT | |
| 2949 | − } | |
| 2950 | − }while ( kpUsedIdPointer[uiNextIdInBs] ); | |
| 2951 | − | |
| 2952 | − // update next_id | |
| 2953 | − sParaSetOffsetVariable->uiNextParaSetIdToUseInBs = uiNextIdInBs; | |
| 2954 | − | |
| 2955 | −#if _DEBUG | |
| 2956 | − assert ( !sParaSetOffsetVariable->bUsedParaSetIdInBs[uiNextIdInBs] ); //sure the next-to-use one is marked activated correctly | |
| 2957 | −#endif | |
| 2958 | − | |
| 2959 | −} | |
| 2960 | − | |
| 2961 | −/*! | |
| 2962 | − * \brief write all parameter sets introduced in SVC extension | |
| 2963 | − * \return size in bytes of bitstream wrote | |
| 2964 | − */ | |
| 2965 | −int32_t WelsWriteParameterSets( sWelsEncCtx *pCtx, int32_t *pNalLen, int32_t *pNumNal ) | |
| 2966 | −{ | |
| 2967 | − int32_t iSize = 0; | |
| 2968 | − int32_t iNal = 0; | |
| 2969 | − int32_t iIdx = 0; | |
| 2970 | − int32_t iId = 0; | |
| 2971 | − int32_t iCountNal = 0; | |
| 2972 | − | |
| 2973 | − if ( NULL == pCtx || NULL == pNalLen || NULL == pNumNal ) | |
| 2974 | − return 0; | |
| 2975 | − | |
| 2976 | − /* write all SPS */ | |
| 2977 | − iIdx = 0; | |
| 2978 | − while (iIdx < pCtx->iSpsNum) { | |
| 2979 | − SDqIdc *pDqIdc = &pCtx->pDqIdcMap[iIdx]; | |
| 2980 | − const int32_t kiDid = pDqIdc->uiSpatialId; | |
| 2981 | − const bool_t kbUsingSubsetSps = (kiDid > BASE_DEPENDENCY_ID); | |
| 2982 | − | |
| 2983 | − iNal = pCtx->pOut->iNalIndex; | |
| 2984 | − | |
| 2985 | − if ( pCtx->pSvcParam->bEnableSpsPpsIdAddition ) | |
| 2986 | − { | |
| 2987 | −#if _DEBUG | |
| 2988 | − pCtx->sPSOVector.bEnableSpsPpsIdAddition = 1; | |
| 2989 | − assert(kiDid < MAX_DEPENDENCY_LAYER); | |
| 2990 | − assert(iIdx < MAX_DQ_LAYER_NUM); | |
| 2991 | −#endif | |
| 2992 | − | |
| 2993 | − ParasetIdAdditionIdAdjust( &(pCtx->sPSOVector.sParaSetOffsetVariable[kbUsingSubsetSps ? PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS]), | |
| 2994 | − (kbUsingSubsetSps)?(pCtx->pSubsetArray[iIdx - 1].pSps.uiSpsId):(pCtx->pSpsArray[0].uiSpsId ), | |
| 2995 | − MAX_SPS_COUNT ); | |
| 2996 | − } | |
| 2997 | − else | |
| 2998 | − { | |
| 2999 | − memset(&(pCtx->sPSOVector), 0, sizeof(pCtx->sPSOVector) ); | |
| 3000 | − } | |
| 3001 | − | |
| 3002 | − if ( kbUsingSubsetSps ){ | |
| 3003 | − iId = iIdx - 1; | |
| 3004 | − | |
| 3005 | − /* generate Subset SPS */ | |
| 3006 | − WelsLoadNal( pCtx->pOut, NAL_UNIT_SUBSET_SPS, NRI_PRI_HIGHEST ); | |
| 3007 | − | |
| 3008 | − WelsWriteSubsetSpsSyntax( &pCtx->pSubsetArray[iId], &pCtx->pOut->sBsWrite, &(pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_SUBSETSPS].iParaSetIdDelta[0]) ); | |
| 3009 | − WelsUnloadNal( pCtx->pOut ); | |
| 3010 | − } | |
| 3011 | − else{ | |
| 3012 | − iId = 0; | |
| 3013 | − | |
| 3014 | − /* generate sequence parameters set */ | |
| 3015 | − WelsLoadNal( pCtx->pOut, NAL_UNIT_SPS, NRI_PRI_HIGHEST ); | |
| 3016 | − WelsWriteSpsNal( &pCtx->pSpsArray[0], &pCtx->pOut->sBsWrite, &(pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_AVCSPS].iParaSetIdDelta[0]) ); | |
| 3017 | − WelsUnloadNal( pCtx->pOut ); | |
| 3018 | − } | |
| 3019 | − | |
| 3020 | − pNalLen[iCountNal] = WelsEncodeNal( &pCtx->pOut->sNalList[iNal], pCtx->pFrameBs + pCtx->iPosBsBuffer, &pNalLen[iCountNal] ); | |
| 3021 | − | |
| 3022 | − pCtx->iPosBsBuffer += pNalLen[iCountNal]; | |
| 3023 | − iSize += pNalLen[iCountNal]; | |
| 3024 | − | |
| 3025 | − ++ iIdx; | |
| 3026 | − ++ iCountNal; | |
| 3027 | − } | |
| 3028 | − | |
| 3029 | − /* write all PPS */ | |
| 3030 | − iIdx = 0; | |
| 3031 | − while (iIdx < pCtx->iPpsNum) { | |
| 3032 | − if ( pCtx->pSvcParam->bEnableSpsPpsIdAddition ) | |
| 3033 | − { | |
| 3034 | − //para_set_type = 2: PPS, use MAX_PPS_COUNT | |
| 3035 | − ParasetIdAdditionIdAdjust( &pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS], pCtx->pPPSArray[iIdx].iPpsId, MAX_PPS_COUNT ); | |
| 3036 | − } | |
| 3037 | − | |
| 3038 | − iNal = pCtx->pOut->iNalIndex; | |
| 3039 | − /* generate picture parameter set */ | |
| 3040 | − WelsLoadNal( pCtx->pOut, NAL_UNIT_PPS, NRI_PRI_HIGHEST ); | |
| 3041 | − WelsWritePpsSyntax( &pCtx->pPPSArray[iIdx], &pCtx->pOut->sBsWrite, &(pCtx->sPSOVector) ); | |
| 3042 | − WelsUnloadNal( pCtx->pOut ); | |
| 3043 | − | |
| 3044 | − pNalLen[iCountNal] = WelsEncodeNal( &pCtx->pOut->sNalList[iNal], pCtx->pFrameBs + pCtx->iPosBsBuffer, &pNalLen[iCountNal] ); | |
| 3045 | − | |
| 3046 | − pCtx->iPosBsBuffer += pNalLen[iCountNal]; | |
| 3047 | − iSize += pNalLen[iCountNal]; | |
| 3048 | − | |
| 3049 | − ++ iIdx; | |
| 3050 | − ++ iCountNal; | |
| 3051 | − } | |
| 3052 | − | |
| 3053 | − *pNumNal = iCountNal; | |
| 3054 | − | |
| 3055 | − return iSize; | |
| 3056 | −} | |
| 3057 | − | |
| 3058 | −static inline int32_t AddPrefixNal( sWelsEncCtx *pCtx, | |
| 3059 | − SLayerBSInfo *pLayerBsInfo, | |
| 3060 | − int32_t *pNalLen, | |
| 3061 | − int32_t *pNalIdxInLayer, | |
| 3062 | − const EWelsNalUnitType keNalType, | |
| 3063 | − const EWelsNalRefIdc keNalRefIdc ) | |
| 3064 | −{ | |
| 3065 | − int32_t iPayloadSize = 0; | |
| 3066 | − | |
| 3067 | − if ( keNalRefIdc != NRI_PRI_LOWEST ) | |
| 3068 | − { | |
| 3069 | − WelsLoadNal( pCtx->pOut, NAL_UNIT_PREFIX, keNalRefIdc ); | |
| 3070 | − | |
| 3071 | − WelsWriteSVCPrefixNal( &pCtx->pOut->sBsWrite, keNalRefIdc, (NAL_UNIT_CODED_SLICE_IDR == keNalType) ); | |
| 3072 | − | |
| 3073 | − WelsUnloadNal( pCtx->pOut ); | |
| 3074 | − | |
| 3075 | − iPayloadSize = WelsEncodeNalExt( &pCtx->pOut->sNalList[pCtx->pOut->iNalIndex-1], | |
| 3076 | − &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt, | |
| 3077 | − pCtx->pFrameBs + pCtx->iPosBsBuffer, | |
| 3078 | − &pNalLen[*pNalIdxInLayer] ); | |
| 3079 | − | |
| 3080 | − pCtx->iPosBsBuffer += iPayloadSize; | |
| 3081 | − pLayerBsInfo->iNalLengthInByte[*pNalIdxInLayer] = iPayloadSize; | |
| 3082 | − | |
| 3083 | − (*pNalIdxInLayer) ++; | |
| 3084 | − } | |
| 3085 | − else // No Prefix NAL Unit RBSP syntax here, but need add NAL Unit Header extension | |
| 3086 | − { | |
| 3087 | − WelsLoadNal( pCtx->pOut, NAL_UNIT_PREFIX, keNalRefIdc ); | |
| 3088 | − // No need write any syntax of prefix NAL Unit RBSP here | |
| 3089 | − WelsUnloadNal( pCtx->pOut ); | |
| 3090 | − | |
| 3091 | − iPayloadSize = WelsEncodeNalExt( &pCtx->pOut->sNalList[pCtx->pOut->iNalIndex-1], | |
| 3092 | − &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt, | |
| 3093 | − pCtx->pFrameBs + pCtx->iPosBsBuffer, | |
| 3094 | − &pNalLen[*pNalIdxInLayer] ); | |
| 3095 | − | |
| 3096 | − pCtx->iPosBsBuffer += iPayloadSize; | |
| 3097 | − pLayerBsInfo->iNalLengthInByte[*pNalIdxInLayer] = iPayloadSize; | |
| 3098 | − | |
| 3099 | − (*pNalIdxInLayer) ++; | |
| 3100 | − } | |
| 3101 | − | |
| 3102 | − return iPayloadSize; | |
| 3103 | −} | |
| 3104 | − | |
| 3105 | −int32_t WritePadding(sWelsEncCtx *pCtx, int32_t iLen) | |
| 3106 | −{ | |
| 3107 | − int32_t i=0; | |
| 3108 | − int32_t iNal = 0; | |
| 3109 | − SBitStringAux *pBs = NULL; | |
| 3110 | − int32_t iNalLen; | |
| 3111 | − int32_t iSize=0; | |
| 3112 | − | |
| 3113 | − iNal = pCtx->pOut->iNalIndex; | |
| 3114 | − pBs = &pCtx->pOut->sBsWrite; // SBitStringAux instance for non VCL NALs decoding | |
| 3115 | − | |
| 3116 | − if((pBs->pBufEnd - pBs->pBufPtr) < iLen || iNal >= pCtx->pOut->iCountNals) | |
| 3117 | − { | |
| 3118 | −#if GOM_TRACE_FLAG | |
| 3119 | − WelsLog( pCtx, WELS_LOG_ERROR,"[RC] paddingcal pBuffer overflow, bufferlen=%d, paddinglen=%d, iNalIdx= %d, iCountNals= %d\n", | |
| 3120 | − (pBs->pBufEnd-pBs->pBufPtr), iLen, iNal, pCtx->pOut->iCountNals); | |
| 3121 | −#endif | |
| 3122 | − return 0; | |
| 3123 | − } | |
| 3124 | − | |
| 3125 | − WelsLoadNal( pCtx->pOut, NAL_UNIT_FILLER_DATA, NRI_PRI_LOWEST ); | |
| 3126 | − | |
| 3127 | − for(i=0;i<iLen;i++) | |
| 3128 | − { | |
| 3129 | − BsWriteBits( pBs, 8, 0xff); | |
| 3130 | − } | |
| 3131 | − | |
| 3132 | − BsRbspTrailingBits( pBs ); | |
| 3133 | − | |
| 3134 | − BsFlush( pBs ); | |
| 3135 | − | |
| 3136 | − WelsUnloadNal( pCtx->pOut ); | |
| 3137 | − iNalLen = WelsEncodeNal( &pCtx->pOut->sNalList[iNal], pCtx->pFrameBs + pCtx->iPosBsBuffer, &iNalLen ); | |
| 3138 | − | |
| 3139 | − pCtx->iPosBsBuffer += iNalLen; | |
| 3140 | − iSize += iNalLen; | |
| 3141 | − | |
| 3142 | − return iSize; | |
| 3143 | −} | |
| 3144 | − | |
| 3145 | −/* | |
| 3146 | − * post process of dynamic slicing bs writing in case PACKING_ONE_SLICE_PER_LAYER | |
| 3147 | − * include: count bs size of over all the slices in layer, | |
| 3148 | − * return: count number of slices in layer | |
| 3149 | − */ | |
| 3150 | −#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 3151 | −int32_t PostProcDynamicSlicingBsWriting( sWelsEncCtx *pCtx, SLayerBSInfo *pLayerBsInfo, int32_t *pLayerSize, const int32_t kiPartitionCnt ) | |
| 3152 | −{ | |
| 3153 | − SDqLayer *pCurDq = pCtx->pCurDqLayer; | |
| 3154 | − int32_t iPartitionIdx = 0; | |
| 3155 | − int32_t iCheckingIdx = 0; | |
| 3156 | − int32_t iSwappingIdx = -1; | |
| 3157 | − int32_t iSliceCount = 0; | |
| 3158 | − int32_t iLayerSize = 0; | |
| 3159 | − | |
| 3160 | − // count number of slices in layer and layer size | |
| 3161 | − while(iPartitionIdx < kiPartitionCnt) | |
| 3162 | − { | |
| 3163 | − const int32_t coded_slice_cnt = pCurDq->pNumSliceCodedOfPartition[iPartitionIdx]; | |
| 3164 | − iLayerSize += pCtx->pSliceThreading->pCountBsSizeInPartition[iPartitionIdx]; | |
| 3165 | − iSliceCount += coded_slice_cnt; | |
| 3166 | − ++ iPartitionIdx; | |
| 3167 | − } | |
| 3168 | − *pLayerSize = iLayerSize; | |
| 3169 | − | |
| 3170 | − // reordering pLayerBs pointers, but do not ensure raster scan order of picture | |
| 3171 | − // just maintain discontinuous items,i.e, | |
| 3172 | − // input: | |
| 3173 | − // partition 1: uiSliceIdx: 0 2 4 6 | |
| 3174 | − // partition 2: uiSliceIdx: 1 3 5 7 9 11 13 | |
| 3175 | − // output: | |
| 3176 | − // uiSliceIdx: 0 1 2 3 4 5 6 7 8 9 10 | |
| 3177 | − iCheckingIdx = 0; | |
| 3178 | − while(true) | |
| 3179 | − { | |
| 3180 | − bool_t bMatchFlag = false; | |
| 3181 | − iPartitionIdx = 0; | |
| 3182 | − while(iPartitionIdx < kiPartitionCnt) | |
| 3183 | − { | |
| 3184 | − const int32_t coded_slice_cnt = pCurDq->pNumSliceCodedOfPartition[iPartitionIdx]; | |
| 3185 | − // iCheckingIdx need convert to iIndex of iPartitionIdx based to avoid linear searching | |
| 3186 | − // belong this partition and not exceed the number of slices coded in partition | |
| 3187 | − if ( iPartitionIdx == (iCheckingIdx % kiPartitionCnt) | |
| 3188 | − && iCheckingIdx / kiPartitionCnt < coded_slice_cnt ) | |
| 3189 | − { | |
| 3190 | − if ( iSwappingIdx >= 0 ) | |
| 3191 | − { | |
| 3192 | − // memory swapping | |
| 3193 | − memmove(pLayerBsInfo+iSwappingIdx, LayerBsInfo+iCheckingIdx, sizeof(SLayerBSInfo)); // confirmed_safe_unsafe_usage | |
| 3194 | − ++ iSwappingIdx; // record iSwappingIdx | |
| 3195 | − } | |
| 3196 | − ++ iCheckingIdx; | |
| 3197 | − bMatchFlag = true; | |
| 3198 | − break; | |
| 3199 | − } | |
| 3200 | − ++ iPartitionIdx; | |
| 3201 | − } | |
| 3202 | − if ( !bMatchFlag ) | |
| 3203 | − { | |
| 3204 | − if ( iSwappingIdx < 0 ) | |
| 3205 | − iSwappingIdx = iCheckingIdx; | |
| 3206 | − ++ iCheckingIdx; | |
| 3207 | − } | |
| 3208 | − if ( iSwappingIdx >= iSliceCount ) | |
| 3209 | − break; | |
| 3210 | − } | |
| 3211 | − | |
| 3212 | − return iSliceCount; | |
| 3213 | −} | |
| 3214 | −#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | |
| 3215 | − | |
| 3216 | −/* | |
| 3217 | − * Force coding IDR as follows | |
| 3218 | − */ | |
| 3219 | −int32_t ForceCodingIDR( sWelsEncCtx *pCtx ) | |
| 3220 | −{ | |
| 3221 | − if ( NULL == pCtx ) | |
| 3222 | − return 1; | |
| 3223 | − | |
| 3224 | − pCtx->bEncCurFrmAsIdrFlag = true; | |
| 3225 | − pCtx->iCodingIndex = 0; | |
| 3226 | − | |
| 3227 | − return 0; | |
| 3228 | −} | |
| 3229 | − | |
| 3230 | −/*! | |
| 3231 | − * \brief core svc encoding process | |
| 3232 | − * | |
| 3233 | − * \pParam pCtx sWelsEncCtx*, encoder context | |
| 3234 | − * \pParam pDst FrameBSInfo* | |
| 3235 | − * \pParam pSrc SSourcePicture* for need_ds = true or SSourcePicture** for need_ds = false | |
| 3236 | − * \pParam iConfiguredLayerNum =1 in case need_ds = true or >1 in case need_ds = false | |
| 3237 | − * \pParam need_ds Indicate whether need down sampling desired | |
| 3238 | − * [NO in picture list case, YES in console aplication based] | |
| 3239 | − * \return EFrameType (WELS_FRAME_TYPE_IDR/WELS_FRAME_TYPE_I/WELS_FRAME_TYPE_P) | |
| 3240 | − */ | |
| 3241 | −int32_t WelsEncoderEncodeExt( sWelsEncCtx *pCtx, void *pDst, const SSourcePicture **ppSrcList, const int32_t iConfiguredLayerNum ) | |
| 3242 | −{ | |
| 3243 | − SFrameBSInfo *pFbi = (SFrameBSInfo *)pDst; | |
| 3244 | − SLayerBSInfo *pLayerBsInfo = &pFbi->sLayerInfo[0]; | |
| 3245 | − SWelsSvcCodingParam *pSvcParam = pCtx->pSvcParam; | |
| 3246 | − SSpatialPicIndex *pSpatialIndexMap= &pCtx->sSpatialIndexMap[0]; | |
| 3247 | −#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC) | |
| 3248 | − SPicture *fsnr = NULL; | |
| 3249 | −#endif//ENABLE_FRAME_DUMP || ENABLE_PSNR_CALC | |
| 3250 | − SPicture *pEncPic = NULL; // to be decided later | |
| 3251 | −#if defined(MT_ENABLED) && (defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG)) | |
| 3252 | − int32_t did_list[MAX_DEPENDENCY_LAYER] = {0}; | |
| 3253 | −#endif//MT_ENABLED && DYNAMIC_SLICE_ASSIGN | |
| 3254 | − int32_t iLayerNum = 0; | |
| 3255 | − int32_t iLayerSize = 0; | |
| 3256 | − int32_t iSpatialNum = 0; // available count number of spatial layers due to frame size changed in this given frame | |
| 3257 | − int32_t iSpatialIdx = 0; // iIndex of spatial layers due to frame size changed in this given frame | |
| 3258 | − int32_t iFrameSize = 0; | |
| 3259 | − int32_t iNalLen[128] = {0}; | |
| 3260 | − int32_t iNalIdxInLayer = 0; | |
| 3261 | − int32_t iCountNal = 0; | |
| 3262 | − EFrameType eFrameType = WELS_FRAME_TYPE_AUTO; | |
| 3263 | − int32_t iCurWidth = 0; | |
| 3264 | − int32_t iCurHeight = 0; | |
| 3265 | − EWelsNalUnitType eNalType = NAL_UNIT_UNSPEC_0; | |
| 3266 | − EWelsNalRefIdc eNalRefIdc = NRI_PRI_LOWEST; | |
| 3267 | − int8_t iCurDid = 0; | |
| 3268 | − int8_t iCurTid = 0; | |
| 3269 | − bool_t bAvcBased = false; | |
| 3270 | −#if defined(ENABLE_PSNR_CALC) | |
| 3271 | − real32_t snr_y = .0f, snr_u = .0f, snr_v = .0f; | |
| 3272 | −#endif//ENABLE_PSNR_CALC | |
| 3273 | − | |
| 3274 | −#if defined(_DEBUG) | |
| 3275 | − int32_t i = 0, j = 0, k = 0; | |
| 3276 | −#endif//_DEBUG | |
| 3277 | − | |
| 3278 | − pFbi->iLayerNum = 0; // for initialization | |
| 3279 | − | |
| 3280 | − // perform csc/denoise/downsample/padding, generate spatial layers | |
| 3281 | − iSpatialNum = pCtx->pVpp->WelsPreprocessStep1(pCtx, ppSrcList, iConfiguredLayerNum); | |
| 3282 | − if ( iSpatialNum < 1 ) // skip due to temporal layer settings (different frame rate) | |
| 3283 | − { | |
| 3284 | − ++ pCtx->iCodingIndex; | |
| 3285 | − return WELS_FRAME_TYPE_SKIP; | |
| 3286 | − } | |
| 3287 | − | |
| 3288 | − eFrameType = DecideFrameType( pCtx, iSpatialNum ); | |
| 3289 | − if (eFrameType == WELS_FRAME_TYPE_SKIP) | |
| 3290 | − return eFrameType; | |
| 3291 | − | |
| 3292 | − InitFrameCoding( pCtx, eFrameType ); | |
| 3293 | − | |
| 3294 | − iCurTid = GetTemporalLevel( &pSvcParam->sDependencyLayers[pSpatialIndexMap->iDid], pCtx->iCodingIndex, pSvcParam->uiGopSize ); | |
| 3295 | − pCtx->uiTemporalId = iCurTid; | |
| 3296 | − | |
| 3297 | − pLayerBsInfo->pBsBuf = pCtx->pFrameBs ; | |
| 3298 | − | |
| 3299 | − if ( eFrameType == WELS_FRAME_TYPE_IDR ) | |
| 3300 | − { | |
| 3301 | − ++ pCtx->sPSOVector.uiIdrPicId; | |
| 3302 | − //if ( pSvcParam->bEnableSSEI ) | |
| 3303 | − | |
| 3304 | − // write parameter sets bitstream here | |
| 3305 | − WelsWriteParameterSets( pCtx, &iNalLen[0], &iCountNal ); | |
| 3306 | − | |
| 3307 | − pLayerBsInfo->uiPriorityId = 0; | |
| 3308 | − pLayerBsInfo->uiSpatialId = 0; | |
| 3309 | − pLayerBsInfo->uiTemporalId = 0; | |
| 3310 | − pLayerBsInfo->uiQualityId = 0; | |
| 3311 | − pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; | |
| 3312 | − pLayerBsInfo->iNalCount = iCountNal; | |
| 3313 | − for (int32_t iNalIndex = 0; iNalIndex < iCountNal; ++ iNalIndex) | |
| 3314 | − { | |
| 3315 | − pLayerBsInfo->iNalLengthInByte[iNalIndex] = iNalLen[iNalIndex]; | |
| 3316 | − } | |
| 3317 | − | |
| 3318 | − ++ pLayerBsInfo; | |
| 3319 | − pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; | |
| 3320 | − ++ iLayerNum; | |
| 3321 | − } | |
| 3322 | − | |
| 3323 | − pCtx->pCurDqLayer = pCtx->ppDqLayerList[pSpatialIndexMap->iDid]; | |
| 3324 | − pCtx->pCurDqLayer->pRefLayer = NULL; | |
| 3325 | − | |
| 3326 | − while ( iSpatialIdx < iSpatialNum ) | |
| 3327 | − { | |
| 3328 | − const int32_t d_idx = (pSpatialIndexMap+iSpatialIdx)->iDid; // get iDid | |
| 3329 | − SDLayerParam *param_d = &pSvcParam->sDependencyLayers[d_idx]; | |
| 3330 | − | |
| 3331 | − pCtx->uiDependencyId = iCurDid = (int8_t)d_idx; | |
| 3332 | − pCtx->pVpp->WelsPreprocessStep3(pCtx, d_idx); | |
| 3333 | − | |
| 3334 | − pCtx->pEncPic = pEncPic = (pSpatialIndexMap+iSpatialIdx)->pSrc; | |
| 3335 | − pCtx->pEncPic->iPictureType = pCtx->eSliceType; | |
| 3336 | − pCtx->pEncPic->iFramePoc = pCtx->iPOC; | |
| 3337 | − | |
| 3338 | − iCurWidth = param_d->iFrameWidth; | |
| 3339 | − iCurHeight = param_d->iFrameHeight; | |
| 3340 | − | |
| 3341 | −#if defined(MT_ENABLED) && (defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG)) | |
| 3342 | − did_list[iSpatialIdx] = iCurDid; | |
| 3343 | −#endif//MT_ENABLED && DYNAMIC_SLICE_ASSIGN | |
| 3344 | − | |
| 3345 | − // Encoding this picture might mulitiple sQualityStat layers potentially be encoded as followed | |
| 3346 | − | |
| 3347 | − switch ( param_d->sMso.uiSliceMode ) | |
| 3348 | − { | |
| 3349 | − case SM_FIXEDSLCNUM_SLICE: | |
| 3350 | − { | |
| 3351 | −#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN) | |
| 3352 | − if ( (iCurDid > 0) && (pSvcParam->iMultipleThreadIdc > 1) && | |
| 3353 | − (pSvcParam->sDependencyLayers[iCurDid].sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE && pSvcParam->iMultipleThreadIdc >= pSvcParam->sDependencyLayers[iCurDid].sMso.sSliceArgument.iSliceNum ) | |
| 3354 | − ) | |
| 3355 | − AdjustEnhanceLayer( pCtx, iCurDid ); | |
| 3356 | −#endif//MT_ENABLED && DYNAMIC_SLICE_ASSIGN | |
| 3357 | − break; | |
| 3358 | − } | |
| 3359 | − case SM_DYN_SLICE: | |
| 3360 | − { | |
| 3361 | − int32_t iPicIPartitionNum = PicPartitionNumDecision( pCtx ); | |
| 3362 | − // MT compatibility | |
| 3363 | − pCtx->iActiveThreadsNum = iPicIPartitionNum; // we try to active number of threads, equal to number of picture partitions | |
| 3364 | − WelsInitCurrentDlayerMltslc( pCtx, iPicIPartitionNum ); | |
| 3365 | − break; | |
| 3366 | − } | |
| 3367 | − default: | |
| 3368 | − { | |
| 3369 | − break; | |
| 3370 | − } | |
| 3371 | − } | |
| 3372 | − | |
| 3373 | − /* coding each spatial layer, only one sQualityStat layer within spatial support */ | |
| 3374 | − int32_t iSliceCount = 1; | |
| 3375 | − if ( iLayerNum >= MAX_LAYER_NUM_OF_FRAME ) // check available layer_bs_info writing as follows | |
| 3376 | − { | |
| 3377 | − WelsLog( pCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iLayerNum(%d) overflow(max:%d)!", iLayerNum, MAX_LAYER_NUM_OF_FRAME); | |
| 3378 | − return -1; | |
| 3379 | − } | |
| 3380 | − | |
| 3381 | − iNalIdxInLayer = 0; | |
| 3382 | − bAvcBased = (iCurDid == BASE_DEPENDENCY_ID); | |
| 3383 | − pCtx->bNeedPrefixNalFlag = (bAvcBased && | |
| 3384 | − (pSvcParam->bPrefixNalAddingCtrl || | |
| 3385 | − (pSvcParam->iNumDependencyLayer > 1) )); | |
| 3386 | − | |
| 3387 | − if ( eFrameType == WELS_FRAME_TYPE_P ) | |
| 3388 | − { | |
| 3389 | − eNalType = bAvcBased ? NAL_UNIT_CODED_SLICE : NAL_UNIT_CODED_SLICE_EXT; | |
| 3390 | − } | |
| 3391 | − else if ( eFrameType == WELS_FRAME_TYPE_IDR ) | |
| 3392 | − { | |
| 3393 | − eNalType = bAvcBased ? NAL_UNIT_CODED_SLICE_IDR : NAL_UNIT_CODED_SLICE_EXT; | |
| 3394 | − } | |
| 3395 | − if ( iCurTid == 0 || pCtx->eSliceType == I_SLICE ) | |
| 3396 | − eNalRefIdc = NRI_PRI_HIGHEST; | |
| 3397 | − else if ( iCurTid == pSvcParam->iDecompStages ) | |
| 3398 | − eNalRefIdc = NRI_PRI_LOWEST; | |
| 3399 | − else if ( 1 + iCurTid == pSvcParam->iDecompStages ) | |
| 3400 | − eNalRefIdc = NRI_PRI_LOW; | |
| 3401 | − else // more details for other temporal layers? | |
| 3402 | − eNalRefIdc = NRI_PRI_HIGHEST; | |
| 3403 | − pCtx->eNalType = eNalType; | |
| 3404 | − pCtx->eNalPriority = eNalRefIdc; | |
| 3405 | − | |
| 3406 | − pCtx->pDecPic = pCtx->ppRefPicListExt[iCurDid]->pNextBuffer; | |
| 3407 | −#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC) | |
| 3408 | − fsnr = pCtx->pDecPic; | |
| 3409 | −#endif//#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC) | |
| 3410 | − pCtx->pDecPic->iPictureType = pCtx->eSliceType; | |
| 3411 | − pCtx->pDecPic->iFramePoc = pCtx->iPOC; | |
| 3412 | − | |
| 3413 | − WelsInitCurrentLayer( pCtx, iCurWidth, iCurHeight ); | |
| 3414 | − | |
| 3415 | − WelsMarkPic(pCtx); | |
| 3416 | − if ( !WelsBuildRefList( pCtx, pCtx->iPOC ) ) | |
| 3417 | − { | |
| 3418 | − // Force coding IDR as followed | |
| 3419 | − ForceCodingIDR( pCtx ); | |
| 3420 | − WelsLog(pCtx, WELS_LOG_WARNING, "WelsEncoderEncodeExt(), WelsBuildRefList failed for P frames, pCtx->iNumRef0= %d.\n", pCtx->iNumRef0); | |
| 3421 | − return -1; | |
| 3422 | − } | |
| 3423 | −#ifdef LONG_TERM_REF_DUMP | |
| 3424 | − dump_ref(pCtx); | |
| 3425 | −#endif | |
| 3426 | − WelsUpdateRefSyntax(pCtx, pCtx->iPOC, eFrameType); //get reordering syntax used for writing slice header and transmit to encoder. | |
| 3427 | − PrefetchReferencePicture( pCtx, eFrameType ); // update reference picture for current pDq layer | |
| 3428 | − | |
| 3429 | − pCtx->pFuncList->pfRc.pfWelsRcPictureInit(pCtx); | |
| 3430 | − PreprocessSliceCoding( pCtx ); // MUST be called after pfWelsRcPictureInit() and WelsInitCurrentLayer() | |
| 3431 | − | |
| 3432 | − iLayerSize = 0; | |
| 3433 | − if ( SM_SINGLE_SLICE == param_d->sMso.uiSliceMode ) // only one slice within a sQualityStat layer | |
| 3434 | − { | |
| 3435 | − int32_t iSliceSize = 0; | |
| 3436 | − | |
| 3437 | − if ( pCtx->bNeedPrefixNalFlag ) | |
| 3438 | − { | |
| 3439 | − iLayerSize += AddPrefixNal( pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, eNalType, eNalRefIdc ); | |
| 3440 | − } | |
| 3441 | − | |
| 3442 | − WelsLoadNal( pCtx->pOut, eNalType, eNalRefIdc ); | |
| 3443 | − | |
| 3444 | − WelsCodeOneSlice( pCtx, 0, eNalType ); | |
| 3445 | − | |
| 3446 | − WelsUnloadNal( pCtx->pOut ); | |
| 3447 | − | |
| 3448 | − iSliceSize = WelsEncodeNalExt( &pCtx->pOut->sNalList[pCtx->pOut->iNalIndex-1], | |
| 3449 | − &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt, | |
| 3450 | − pCtx->pFrameBs + pCtx->iPosBsBuffer, | |
| 3451 | − &iNalLen[iNalIdxInLayer] ); | |
| 3452 | − iLayerSize += iSliceSize; | |
| 3453 | − pCtx->iPosBsBuffer += iSliceSize; | |
| 3454 | − pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER; | |
| 3455 | − pLayerBsInfo->uiSpatialId = iCurDid; | |
| 3456 | − pLayerBsInfo->uiTemporalId = iCurTid; | |
| 3457 | − pLayerBsInfo->uiQualityId = 0; | |
| 3458 | − pLayerBsInfo->uiPriorityId = 0; | |
| 3459 | − pLayerBsInfo->iNalLengthInByte[iNalIdxInLayer] = iSliceSize; | |
| 3460 | − pLayerBsInfo->iNalCount = ++ iNalIdxInLayer; | |
| 3461 | − } | |
| 3462 | − // for dynamic slicing single threading.. | |
| 3463 | −#ifndef MT_ENABLED | |
| 3464 | − else if ( SM_DYN_SLICE == param_d->sMso.uiSliceMode ) | |
| 3465 | −#else // MT_ENABLED | |
| 3466 | − else if ( (SM_DYN_SLICE == param_d->sMso.uiSliceMode) && (pSvcParam->iMultipleThreadIdc <= 1) ) | |
| 3467 | −#endif//MT_ENABLED | |
| 3468 | − { | |
| 3469 | − const int32_t kiLastMbInFrame = pCtx->pCurDqLayer->pSliceEncCtx->iMbNumInFrame; | |
| 3470 | − WelsCodeOnePicPartition( pCtx, pLayerBsInfo, &iNalIdxInLayer, &iLayerSize, 0, kiLastMbInFrame, 0 ); | |
| 3471 | − } | |
| 3472 | − else | |
| 3473 | − {//other multi-slice uiSliceMode | |
| 3474 | −#if defined(MT_ENABLED) | |
| 3475 | − int err = 0; | |
| 3476 | − // THREAD_FULLY_FIRE_MODE/THREAD_PICK_UP_MODE for any mode of non-SM_DYN_SLICE | |
| 3477 | − if ( (SM_DYN_SLICE != param_d->sMso.uiSliceMode) && (pSvcParam->iMultipleThreadIdc > 1) ) | |
| 3478 | − { | |
| 3479 | − iSliceCount = GetCurrentSliceNum( pCtx->pCurDqLayer->pSliceEncCtx ); | |
| 3480 | − if ( iLayerNum + | |
| 3481 | −#if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 3482 | − iSliceCount | |
| 3483 | −#else | |
| 3484 | − 1 | |
| 3485 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 3486 | − >= MAX_LAYER_NUM_OF_FRAME ) // check available layer_bs_info for further writing as followed | |
| 3487 | − { | |
| 3488 | − WelsLog( pCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iLayerNum(%d) overflow(max:%d) at iDid= %d uiSliceMode= %d, iSliceCount= %d!", | |
| 3489 | − iLayerNum, MAX_LAYER_NUM_OF_FRAME, iCurDid, param_d->sMso.uiSliceMode, iSliceCount ); | |
| 3490 | − return -1; | |
| 3491 | − } | |
| 3492 | − if ( iSliceCount <= 1 ) | |
| 3493 | − { | |
| 3494 | − WelsLog( pCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iSliceCount(%d) from GetCurrentSliceNum() is untrusted due stack/heap crupted!\n", iSliceCount ); | |
| 3495 | − return -1; | |
| 3496 | − } | |
| 3497 | − | |
| 3498 | − if ( pSvcParam->iCountThreadsNum >= iSliceCount ) //THREAD_FULLY_FIRE_MODE | |
| 3499 | − { | |
| 3500 | −#if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 3501 | − int32_t iSliceIdx = 1; | |
| 3502 | − int32_t iOrgSlicePos[MAX_SLICES_NUM] = {0}; | |
| 3503 | − iOrgSlicePos[0] = pCtx->iPosBsBuffer; | |
| 3504 | − while (uiSliceIdx < iSliceCount) | |
| 3505 | − { | |
| 3506 | − iOrgSlicePos[uiSliceIdx] = pCtx->pSliceBs[uiSliceIdx].uiBsPos; | |
| 3507 | − ++ uiSliceIdx; | |
| 3508 | − } | |
| 3509 | −#elif defined(MT_DEBUG) | |
| 3510 | − int64_t t_bs_append = 0; | |
| 3511 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 3512 | − | |
| 3513 | − pCtx->iActiveThreadsNum = iSliceCount; | |
| 3514 | − // to fire slice coding threads | |
| 3515 | − err = FiredSliceThreads( &pCtx->pSliceThreading->pThreadPEncCtx[0], &pCtx->pSliceThreading->pReadySliceCodingEvent[0], pLayerBsInfo, iSliceCount, pCtx->pCurDqLayer->pSliceEncCtx, FALSE ); | |
| 3516 | − if ( err ) | |
| 3517 | − { | |
| 3518 | − WelsLog( pCtx, WELS_LOG_ERROR, "[MT] WelsEncoderEncodeExt(), FiredSliceThreads return(%d) failed and exit encoding frame, iCountThreadsNum= %d, iSliceCount= %d, uiSliceMode= %d, iMultipleThreadIdc= %d!!\n", | |
| 3519 | − err, pSvcParam->iCountThreadsNum, iSliceCount, param_d->sMso.uiSliceMode, pSvcParam->iMultipleThreadIdc ); | |
| 3520 | − return -1; | |
| 3521 | − } | |
| 3522 | − | |
| 3523 | − WelsMultipleEventsWaitAllBlocking( iSliceCount, &pCtx->pSliceThreading->pSliceCodedEvent[0] ); | |
| 3524 | − | |
| 3525 | − | |
| 3526 | − // all slices are finished coding here | |
| 3527 | − // append exclusive slice 0 bs to pFrameBs | |
| 3528 | −#if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 3529 | − iLayerSize = pCtx->iPosBsBuffer - iOrgSlicePos[0]; | |
| 3530 | − uiSliceIdx = 1; | |
| 3531 | − while (uiSliceIdx < iSliceCount) | |
| 3532 | − { | |
| 3533 | − iLayerSize += pCtx->pSliceBs[uiSliceIdx].uiBsPos - iOrgSlicePos[uiSliceIdx]; | |
| 3534 | − ++ uiSliceIdx; | |
| 3535 | − } | |
| 3536 | − iLayerNum += iSliceCount; // each slice stickly output as layer info for performance improvement directly | |
| 3537 | − pLayerBsInfo += iSliceCount; | |
| 3538 | −#else | |
| 3539 | −#if defined(MT_DEBUG) | |
| 3540 | − t_bs_append = WelsTime(); | |
| 3541 | −#endif//MT_DEBUG | |
| 3542 | − iLayerSize = AppendSliceToFrameBs( pCtx, pLayerBsInfo, iSliceCount ); | |
| 3543 | −#if defined(MT_DEBUG) | |
| 3544 | − t_bs_append = WelsTime() - t_bs_append; | |
| 3545 | − if ( pCtx->pSliceThreading->pFSliceDiff ) | |
| 3546 | − { | |
| 3547 | − fprintf(pCtx->pSliceThreading->pFSliceDiff, | |
| 3548 | −#if defined(WIN32) | |
| 3549 | − "%6I64d us consumed at AppendSliceToFrameBs() for coding_idx: %d iDid: %d qid: %d\n", | |
| 3550 | −#else | |
| 3551 | − "%6lld us consumed at AppendSliceToFrameBs() for coding_idx: %d iDid: %d qid: %d\n", | |
| 3552 | −#endif//WIN32 | |
| 3553 | − t_bs_append, pCtx->iCodingIndex, iCurDid, 0 ); | |
| 3554 | − } | |
| 3555 | −#endif//MT_DEBUG | |
| 3556 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 3557 | − } | |
| 3558 | − else //THREAD_PICK_UP_MODE | |
| 3559 | − { | |
| 3560 | − int32_t iNumThreadsRunning = 0; | |
| 3561 | − int32_t iNumThreadsScheduled = 0; | |
| 3562 | − int32_t iIndexOfSliceToBeCoded = 0; | |
| 3563 | −#if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 3564 | − int32_t iSliceIdx = 1; | |
| 3565 | − int32_t iOrgSlicePos[MAX_SLICES_NUM] = {0}; | |
| 3566 | − iOrgSlicePos[0] = pCtx->iPosBsBuffer; | |
| 3567 | − while (uiSliceIdx < iSliceCount) | |
| 3568 | − { | |
| 3569 | − iOrgSlicePos[uiSliceIdx] = pCtx->pSliceBs[uiSliceIdx].uiBsPos; | |
| 3570 | − ++ uiSliceIdx; | |
| 3571 | − } | |
| 3572 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 3573 | − | |
| 3574 | − pCtx->iActiveThreadsNum = pSvcParam->iCountThreadsNum; | |
| 3575 | − iNumThreadsScheduled = pCtx->iActiveThreadsNum; | |
| 3576 | − iNumThreadsRunning = iNumThreadsScheduled; | |
| 3577 | − // to fire slice coding threads | |
| 3578 | − err = FiredSliceThreads( &pCtx->pSliceThreading->pThreadPEncCtx[0], &pCtx->pSliceThreading->pReadySliceCodingEvent[0], pLayerBsInfo, iNumThreadsRunning, pCtx->pCurDqLayer->pSliceEncCtx, FALSE ); | |
| 3579 | − if ( err ) | |
| 3580 | − { | |
| 3581 | − WelsLog( pCtx, WELS_LOG_ERROR, "[MT] WelsEncoderEncodeExt(), FiredSliceThreads return(%d) failed and exit encoding frame, iCountThreadsNum= %d, iSliceCount= %d, uiSliceMode= %d, iMultipleThreadIdc= %d!!\n", | |
| 3582 | − err, pSvcParam->iCountThreadsNum, iSliceCount, param_d->sMso.uiSliceMode, pSvcParam->iMultipleThreadIdc ); | |
| 3583 | − return -1; | |
| 3584 | − } | |
| 3585 | − | |
| 3586 | − iIndexOfSliceToBeCoded = iNumThreadsRunning; | |
| 3587 | − while (1) | |
| 3588 | − { | |
| 3589 | − if ( iIndexOfSliceToBeCoded >= iSliceCount && iNumThreadsRunning <= 0 ) | |
| 3590 | − break; | |
| 3591 | −#ifdef WIN32 | |
| 3592 | − WELS_THREAD_ERROR_CODE lwait = 0; | |
| 3593 | − int32_t iEventId = -1; | |
| 3594 | − | |
| 3595 | − lwait = WelsMultipleEventsWaitSingleBlocking( iNumThreadsScheduled, | |
| 3596 | − &pCtx->pSliceThreading->pSliceCodedEvent[0], | |
| 3597 | − 2 ); // 2 ms for one tick | |
| 3598 | − iEventId = (int32_t)(lwait - WELS_THREAD_ERROR_WAIT_OBJECT_0); | |
| 3599 | − if ( iEventId >= 0 && iEventId < iNumThreadsScheduled ) | |
| 3600 | − { | |
| 3601 | − if ( iIndexOfSliceToBeCoded < iSliceCount ) | |
| 3602 | − { | |
| 3603 | − // pick up succeeding slice for threading | |
| 3604 | − // thread_id equal to iEventId per implementation here | |
| 3605 | − pCtx->pSliceThreading->pThreadPEncCtx[iEventId].iSliceIndex = iIndexOfSliceToBeCoded; | |
| 3606 | −#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 3607 | − pCtx->pSliceThreading->pThreadPEncCtx[iEventId].pLayerBs = pLayerBsInfo+iIndexOfSliceToBeCoded; | |
| 3608 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 3609 | − WelsEventSignal( &pCtx->pSliceThreading->pReadySliceCodingEvent[iEventId] ); | |
| 3610 | − | |
| 3611 | − ++ iIndexOfSliceToBeCoded; | |
| 3612 | − } | |
| 3613 | − else // no other slices left for coding | |
| 3614 | − { | |
| 3615 | − -- iNumThreadsRunning; | |
| 3616 | − } | |
| 3617 | − } | |
| 3618 | − else | |
| 3619 | − { | |
| 3620 | − WelsSleep(1); | |
| 3621 | − } | |
| 3622 | −#else//__GNUC__ | |
| 3623 | − // TODO for pthread platforms | |
| 3624 | − // alternate implementation using blocking due non-blocking with timeout mode not support at wels thread lib, tune back if available | |
| 3625 | − WelsMultipleEventsWaitAllBlocking( iNumThreadsRunning, &pCtx->pSliceThreading->pSliceCodedEvent[0] ); | |
| 3626 | − if ( iIndexOfSliceToBeCoded < iSliceCount ) | |
| 3627 | − { | |
| 3628 | − int32_t iThreadIdx = 0; | |
| 3629 | − // pick up succeeding slices for threading if left | |
| 3630 | − while ( iThreadIdx < iNumThreadsScheduled ) | |
| 3631 | − { | |
| 3632 | − if ( iIndexOfSliceToBeCoded >= iSliceCount ) | |
| 3633 | − break; | |
| 3634 | − pCtx->pSliceThreading->pThreadPEncCtx[iThreadIdx].iSliceIndex = iIndexOfSliceToBeCoded; | |
| 3635 | −#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 3636 | − pCtx->pSliceThreading->pThreadPEncCtx[iThreadIdx].pLayerBs = pLayerBsInfo+iIndexOfSliceToBeCoded; | |
| 3637 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 3638 | − WelsEventSignal( pCtx->pSliceThreading->pReadySliceCodingEvent[iThreadIdx] ); | |
| 3639 | − | |
| 3640 | − ++ iIndexOfSliceToBeCoded; | |
| 3641 | − ++ iThreadIdx; | |
| 3642 | − } | |
| 3643 | − // update iNumThreadsRunning | |
| 3644 | − iNumThreadsRunning = iThreadIdx; | |
| 3645 | − } | |
| 3646 | − else | |
| 3647 | − { | |
| 3648 | − iNumThreadsRunning = 0; | |
| 3649 | − } | |
| 3650 | −#endif//WIN32 | |
| 3651 | − }//while(1) | |
| 3652 | − | |
| 3653 | −// all slices are finished coding here | |
| 3654 | − // append exclusive slice 0 bs to pFrameBs | |
| 3655 | −#if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 3656 | − iLayerSize = pCtx->iPosBsBuffer - iOrgSlicePos[0]; | |
| 3657 | − uiSliceIdx = 1; | |
| 3658 | − while (uiSliceIdx < iSliceCount) | |
| 3659 | − { | |
| 3660 | − iLayerSize += pCtx->pSliceBs[uiSliceIdx].uiBsPos - iOrgSlicePos[uiSliceIdx]; | |
| 3661 | − ++ uiSliceIdx; | |
| 3662 | − } | |
| 3663 | − iLayerNum += iSliceCount; // each slice stickly output as layer info for performance improvement directly | |
| 3664 | − pLayerBsInfo += iSliceCount; | |
| 3665 | −#else | |
| 3666 | − iLayerSize = AppendSliceToFrameBs( pCtx, pLayerBsInfo, iSliceCount ); | |
| 3667 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 3668 | − } | |
| 3669 | − } | |
| 3670 | − // THREAD_FULLY_FIRE_MODE && SM_DYN_SLICE | |
| 3671 | − else if ( (SM_DYN_SLICE == param_d->sMso.uiSliceMode) && (pSvcParam->iMultipleThreadIdc > 1) ) | |
| 3672 | − { | |
| 3673 | − const int32_t kiPartitionCnt = pCtx->iActiveThreadsNum; //pSvcParam->iCountThreadsNum; | |
| 3674 | −#if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 3675 | − ResetCountBsSizeInPartitions( pCtx->pSliceThreading->pCountBsSizeInPartition, kiPartitionCnt ); | |
| 3676 | − pCtx->pCurDqLayer->pSliceEncCtx->iMaxSliceNumConstraint = WELS_MIN ( MAX_SLICES_NUM, DynamicMaxSliceNumConstraint( MAX_LAYER_NUM_OF_FRAME, iLayerNum, 1 + /*( num_qlayer - 1) +*/ ( ( (iCurDid==0) && ( pSvcParam->uiGopSize>1 ) ) ? 1: 0 ) ) ); | |
| 3677 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 3678 | − | |
| 3679 | − // to fire slice coding threads | |
| 3680 | − err = FiredSliceThreads( &pCtx->pSliceThreading->pThreadPEncCtx[0], &pCtx->pSliceThreading->pReadySliceCodingEvent[0], pLayerBsInfo, kiPartitionCnt, pCtx->pCurDqLayer->pSliceEncCtx, TRUE ); | |
| 3681 | − if ( err ) | |
| 3682 | − { | |
| 3683 | − WelsLog( pCtx, WELS_LOG_ERROR, "[MT] WelsEncoderEncodeExt(), FiredSliceThreads return(%d) failed and exit encoding frame, iCountThreadsNum= %d, iSliceCount= %d, uiSliceMode= %d, iMultipleThreadIdc= %d!!\n", | |
| 3684 | − err, pSvcParam->iCountThreadsNum, iSliceCount, param_d->sMso.uiSliceMode, pSvcParam->iMultipleThreadIdc ); | |
| 3685 | − return -1; | |
| 3686 | − } | |
| 3687 | − | |
| 3688 | − WelsMultipleEventsWaitAllBlocking( kiPartitionCnt, &pCtx->pSliceThreading->pSliceCodedEvent[0] ); | |
| 3689 | − | |
| 3690 | −#if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 3691 | − iSliceCount = PostProcDynamicSlicingBsWriting( pCtx, pLayerBsInfo, &iLayerSize, kiPartitionCnt ); | |
| 3692 | − assert(iLayerNum + iSliceCount < MAX_LAYER_NUM_OF_FRAME); | |
| 3693 | − pLayerBsInfo += iSliceCount; | |
| 3694 | − iLayerNum += iSliceCount; | |
| 3695 | −#else | |
| 3696 | − iLayerSize = AppendSliceToFrameBs( pCtx, pLayerBsInfo, kiPartitionCnt ); | |
| 3697 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 3698 | − } | |
| 3699 | − else // for non-dynamic-slicing mode single threading branch.. | |
| 3700 | −#endif//MT_ENABLED | |
| 3701 | − { | |
| 3702 | − const bool_t bNeedPrefix = pCtx->bNeedPrefixNalFlag; | |
| 3703 | − int32_t iSliceIdx = 0; | |
| 3704 | − | |
| 3705 | − iSliceCount = GetCurrentSliceNum( pCtx->pCurDqLayer->pSliceEncCtx ); | |
| 3706 | − while (iSliceIdx < iSliceCount) | |
| 3707 | − { | |
| 3708 | − int32_t iSliceSize = 0; | |
| 3709 | − | |
| 3710 | − if ( bNeedPrefix ) | |
| 3711 | − { | |
| 3712 | − iLayerSize += AddPrefixNal( pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, eNalType, eNalRefIdc ); | |
| 3713 | − } | |
| 3714 | − | |
| 3715 | − WelsLoadNal( pCtx->pOut, eNalType, eNalRefIdc ); | |
| 3716 | − WelsCodeOneSlice( pCtx, iSliceIdx, eNalType ); | |
| 3717 | − WelsUnloadNal( pCtx->pOut ); | |
| 3718 | − | |
| 3719 | − iSliceSize = WelsEncodeNalExt( &pCtx->pOut->sNalList[pCtx->pOut->iNalIndex-1], | |
| 3720 | − &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt, | |
| 3721 | − pCtx->pFrameBs + pCtx->iPosBsBuffer, | |
| 3722 | − &iNalLen[iNalIdxInLayer] ); | |
| 3723 | − pCtx->iPosBsBuffer += iSliceSize; | |
| 3724 | − iLayerSize += iSliceSize; | |
| 3725 | − pLayerBsInfo->iNalLengthInByte[iNalIdxInLayer] = iSliceSize; | |
| 3726 | − | |
| 3727 | −#if defined(SLICE_INFO_OUTPUT) | |
| 3728 | − fprintf( stderr, | |
| 3729 | − "@slice=%-6d sliceType:%c idc:%d size:%-6d\n", | |
| 3730 | − iSliceIdx, | |
| 3731 | − (pCtx->eSliceType == P_SLICE ? 'P' : 'I'), | |
| 3732 | − eNalRefIdc, | |
| 3733 | − iSliceSize ); | |
| 3734 | −#endif//SLICE_INFO_OUTPUT | |
| 3735 | − ++ iNalIdxInLayer; | |
| 3736 | − ++ iSliceIdx; | |
| 3737 | − } | |
| 3738 | − | |
| 3739 | − pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER; | |
| 3740 | − pLayerBsInfo->uiSpatialId = iCurDid; | |
| 3741 | − pLayerBsInfo->uiTemporalId = iCurTid; | |
| 3742 | − pLayerBsInfo->uiQualityId = 0; | |
| 3743 | − pLayerBsInfo->uiPriorityId = 0; | |
| 3744 | − pLayerBsInfo->iNalCount = iNalIdxInLayer; | |
| 3745 | − } | |
| 3746 | − } | |
| 3747 | − | |
| 3748 | − // deblocking filter | |
| 3749 | − if ( | |
| 3750 | −#if defined(MT_ENABLED) | |
| 3751 | − (!pCtx->pCurDqLayer->bDeblockingParallelFlag) && | |
| 3752 | −#endif//MT_ENABLED | |
| 3753 | −#if !defined(ENABLE_FRAME_DUMP) | |
| 3754 | − ( (eNalRefIdc != NRI_PRI_LOWEST) && (param_d->iHighestTemporalId == 0 || iCurTid < param_d->iHighestTemporalId) ) && | |
| 3755 | −#endif//!ENABLE_FRAME_DUMP | |
| 3756 | − true | |
| 3757 | − ) | |
| 3758 | − { | |
| 3759 | − PerformDeblockingFilter( pCtx ); | |
| 3760 | − } | |
| 3761 | − | |
| 3762 | − // reference picture list update | |
| 3763 | − if ( eNalRefIdc != NRI_PRI_LOWEST ) | |
| 3764 | − { | |
| 3765 | − if ( !WelsUpdateRefList( pCtx ) ) | |
| 3766 | − { | |
| 3767 | − // Force coding IDR as followed | |
| 3768 | − ForceCodingIDR( pCtx ); | |
| 3769 | − WelsLog(pCtx, WELS_LOG_WARNING, "WelsEncoderEncodeExt(), WelsUpdateRefList failed.\n"); | |
| 3770 | − return -1; | |
| 3771 | − } | |
| 3772 | − } | |
| 3773 | − | |
| 3774 | − iFrameSize += iLayerSize; | |
| 3775 | − | |
| 3776 | − pCtx->pFuncList->pfRc.pfWelsRcPictureInfoUpdate(pCtx, iLayerSize); | |
| 3777 | − | |
| 3778 | −#ifdef ENABLE_FRAME_DUMP | |
| 3779 | − // Dump reconstruction picture for each sQualityStat layer | |
| 3780 | − if ( iCurDid+1 < pSvcParam->iNumDependencyLayer ) | |
| 3781 | − DumpDependencyRec( fsnr, ¶m_d->sRecFileName[0], iCurDid ); | |
| 3782 | −#endif//ENABLE_FRAME_DUMP | |
| 3783 | − | |
| 3784 | −#if defined(ENABLE_PSNR_CALC) | |
| 3785 | − snr_y = WelsCalcPsnr( fsnr->pData[0], | |
| 3786 | − fsnr->iLineSize[0], | |
| 3787 | − pEncPic->pData[0], | |
| 3788 | − pEncPic->iLineSize[0], | |
| 3789 | − iCurWidth, | |
| 3790 | − iCurHeight ); | |
| 3791 | − snr_u = WelsCalcPsnr( fsnr->pData[1], | |
| 3792 | − fsnr->iLineSize[1], | |
| 3793 | − pEncPic->pData[1], | |
| 3794 | − pEncPic->iLineSize[1], | |
| 3795 | − (iCurWidth>>1), | |
| 3796 | − (iCurHeight>>1) ); | |
| 3797 | − snr_v = WelsCalcPsnr( fsnr->pData[2], | |
| 3798 | − fsnr->iLineSize[2], | |
| 3799 | − pEncPic->pData[2], | |
| 3800 | − pEncPic->iLineSize[2], | |
| 3801 | − (iCurWidth>>1), | |
| 3802 | − (iCurHeight>>1) ); | |
| 3803 | −#endif//ENABLE_PSNR_CALC | |
| 3804 | − | |
| 3805 | −#if defined(LAYER_INFO_OUTPUT) | |
| 3806 | − fprintf( stderr, "%2s %5d: %-5d %2s T%1d D%1d Q%-2d QP%3d Y%2.2f U%2.2f V%2.2f %8d bits\n", | |
| 3807 | − (iSpatialIdx == 0) ? "#AU" : " ", | |
| 3808 | − pCtx->iPOC, | |
| 3809 | − pCtx->iFrameNum, | |
| 3810 | − (uiFrameType == WELS_FRAME_TYPE_I || uiFrameType == WELS_FRAME_TYPE_IDR) ? "I": "P", | |
| 3811 | − iCurTid, | |
| 3812 | − iCurDid, | |
| 3813 | − 0, | |
| 3814 | − pCtx->pWelsSvcRc[pCtx->uiDependencyId].iAverageFrameQp, | |
| 3815 | − snr_y, | |
| 3816 | − snr_u, | |
| 3817 | − snr_v, | |
| 3818 | − (iLayerSize<<3) ); | |
| 3819 | −#endif//LAYER_INFO_OUTPUT | |
| 3820 | − | |
| 3821 | −#if defined(STAT_OUTPUT) | |
| 3822 | − | |
| 3823 | −#if defined(ENABLE_PSNR_CALC) | |
| 3824 | − { | |
| 3825 | − pCtx->sStatData[iCurDid][0].sQualityStat.rYPsnr[pCtx->eSliceType] += snr_y; | |
| 3826 | − pCtx->sStatData[iCurDid][0].sQualityStat.rUPsnr[pCtx->eSliceType] += snr_u; | |
| 3827 | − pCtx->sStatData[iCurDid][0].sQualityStat.rVPsnr[pCtx->eSliceType] += snr_v; | |
| 3828 | − } | |
| 3829 | −#endif//ENABLE_PSNR_CALC | |
| 3830 | − | |
| 3831 | −#if defined(MB_TYPES_CHECK) //091025, frame output | |
| 3832 | − if (pCtx->eSliceType == P_SLICE) | |
| 3833 | − { | |
| 3834 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Intra4x4] += pCtx->sPerInfo.iMbCount[P_SLICE][Intra4x4]; | |
| 3835 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Intra16x16] += pCtx->sPerInfo.iMbCount[P_SLICE][Intra16x16]; | |
| 3836 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter16x16] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter16x16]; | |
| 3837 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter16x8] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter16x8]; | |
| 3838 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter8x16] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter8x16]; | |
| 3839 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter8x8] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter8x8]; | |
| 3840 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][PSkip] += pCtx->sPerInfo.iMbCount[P_SLICE][PSkip]; | |
| 3841 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][8] += pCtx->sPerInfo.iMbCount[P_SLICE][8]; | |
| 3842 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][9] += pCtx->sPerInfo.iMbCount[P_SLICE][9]; | |
| 3843 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][10] += pCtx->sPerInfo.iMbCount[P_SLICE][10]; | |
| 3844 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][11] += pCtx->sPerInfo.iMbCount[P_SLICE][11]; | |
| 3845 | − } | |
| 3846 | − else if (pCtx->eSliceType == I_SLICE) | |
| 3847 | − { | |
| 3848 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[I_SLICE][Intra4x4] += pCtx->sPerInfo.iMbCount[I_SLICE][Intra4x4]; | |
| 3849 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[I_SLICE][Intra16x16] += pCtx->sPerInfo.iMbCount[I_SLICE][Intra16x16]; | |
| 3850 | − pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[I_SLICE][7] += pCtx->sPerInfo.iMbCount[I_SLICE][7]; | |
| 3851 | − } | |
| 3852 | − | |
| 3853 | − memset(pCtx->sPerInfo.iMbCount[P_SLICE], 0, 18*sizeof( int32_t )); | |
| 3854 | − memset(pCtx->sPerInfo.iMbCount[I_SLICE], 0, 18*sizeof( int32_t )); | |
| 3855 | − | |
| 3856 | −#endif//MB_TYPES_CHECK | |
| 3857 | − { | |
| 3858 | − //no pCtx->pSvcParam->bMgsT0OnlyStrategy | |
| 3859 | − ++ pCtx->sStatData[iCurDid][0].sSliceData.iSliceCount[pCtx->eSliceType]; // for multiple slices coding | |
| 3860 | − pCtx->sStatData[iCurDid][0].sSliceData.iSliceSize[pCtx->eSliceType] += (iLayerSize<<3); // bits | |
| 3861 | − } | |
| 3862 | −#endif//STAT_OUTPUT | |
| 3863 | − | |
| 3864 | −#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 3865 | − if ( pSvcParam->iMultipleThreadIdc <= 1 || SM_SINGLE_SLICE == param_d->sMso.uiSliceMode ) // sigle thread actually used | |
| 3866 | −#else | |
| 3867 | − if ( 1 ) | |
| 3868 | −#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | |
| 3869 | − { | |
| 3870 | − ++ iLayerNum; | |
| 3871 | − ++ pLayerBsInfo; | |
| 3872 | − } | |
| 3873 | − | |
| 3874 | − | |
| 3875 | − pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; | |
| 3876 | − | |
| 3877 | − if( pSvcParam->iPaddingFlag && pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize > 0 ) | |
| 3878 | − { | |
| 3879 | − const int32_t kiPaddingNalSize = WritePadding(pCtx, pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize); | |
| 3880 | − | |
| 3881 | −#if GOM_TRACE_FLAG | |
| 3882 | − WelsLog( pCtx, WELS_LOG_INFO,"[RC] encoding_qp%d Padding: %d\n",pCtx->uiDependencyId, pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize); | |
| 3883 | −#endif | |
| 3884 | − if ( kiPaddingNalSize <= 0 ) | |
| 3885 | − return -1; | |
| 3886 | − | |
| 3887 | − pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingBitrateStat += pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize; | |
| 3888 | − | |
| 3889 | − pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize=0; | |
| 3890 | − | |
| 3891 | − pLayerBsInfo->uiPriorityId = 0; | |
| 3892 | − pLayerBsInfo->uiSpatialId = 0; | |
| 3893 | − pLayerBsInfo->uiTemporalId = 0; | |
| 3894 | − pLayerBsInfo->uiQualityId = 0; | |
| 3895 | − pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; | |
| 3896 | − pLayerBsInfo->iNalCount = 1; | |
| 3897 | − pLayerBsInfo->iNalLengthInByte[0] = kiPaddingNalSize; | |
| 3898 | − ++ pLayerBsInfo; | |
| 3899 | − pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; | |
| 3900 | − ++ iLayerNum; | |
| 3901 | − } | |
| 3902 | − | |
| 3903 | −#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 3904 | − if ( param_d->sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE && pSvcParam->iMultipleThreadIdc > 1 && | |
| 3905 | − pSvcParam->iMultipleThreadIdc >= param_d->sMso.sSliceArgument.iSliceNum ) | |
| 3906 | − { | |
| 3907 | − CalcSliceComplexRatio( pCtx->pSliceThreading->pSliceComplexRatio[iCurDid], pCtx->pCurDqLayer->pSliceEncCtx, pCtx->pSliceThreading->pSliceConsumeTime[iCurDid] ); | |
| 3908 | −#if defined(MT_DEBUG) | |
| 3909 | − TrackSliceComplexities( pCtx, iCurDid ); | |
| 3910 | −#endif//#if defined(MT_DEBUG) | |
| 3911 | − } | |
| 3912 | −#endif//MT_ENABLED && DYNAMIC_SLICE_ASSIGN && TRY_SLICING_BALANCE | |
| 3913 | − | |
| 3914 | − ++ iSpatialIdx; | |
| 3915 | − | |
| 3916 | − if ( iCurDid+1 < pSvcParam->iNumDependencyLayer ) | |
| 3917 | − { | |
| 3918 | − WelsSwapDqLayers( pCtx ); | |
| 3919 | − } | |
| 3920 | − | |
| 3921 | − if ( pSvcParam->bEnableLongTermReference && (pCtx->pLtr[pCtx->uiDependencyId].bLTRMarkingFlag && (pCtx->pLtr[pCtx->uiDependencyId].iLTRMarkMode == LTR_DELAY_MARK))) | |
| 3922 | − { | |
| 3923 | − pCtx->bLongTermRefFlag[d_idx][0] = true; | |
| 3924 | − } | |
| 3925 | − | |
| 3926 | − if ( iCurTid < pCtx->uiSpatialLayersInTemporal[d_idx] - 1 || pSvcParam->iDecompStages == 0 ) | |
| 3927 | − { | |
| 3928 | − if ( (iCurTid >= MAX_TEMPORAL_LEVEL)||(pCtx->uiSpatialLayersInTemporal[d_idx]-1>= MAX_TEMPORAL_LEVEL)) | |
| 3929 | − { | |
| 3930 | − ForceCodingIDR( pCtx ); // some logic error | |
| 3931 | − return -1; | |
| 3932 | − } | |
| 3933 | − | |
| 3934 | − if ( pSvcParam->bEnableLongTermReference && pCtx->bLongTermRefFlag[d_idx][iCurTid] ) | |
| 3935 | − { | |
| 3936 | − SPicture *tmp = pCtx->pSpatialPic[d_idx][pCtx->uiSpatialLayersInTemporal[d_idx]+pCtx->pVaa->uiMarkLongTermPicIdx]; | |
| 3937 | − pCtx->pSpatialPic[d_idx][pCtx->uiSpatialLayersInTemporal[d_idx]+pCtx->pVaa->uiMarkLongTermPicIdx] = pCtx->pSpatialPic[d_idx][iCurTid]; | |
| 3938 | − pCtx->pSpatialPic[d_idx][iCurTid] = pCtx->pSpatialPic[d_idx][pCtx->uiSpatialLayersInTemporal[d_idx]-1]; | |
| 3939 | − pCtx->pSpatialPic[d_idx][pCtx->uiSpatialLayersInTemporal[d_idx]-1] = tmp; | |
| 3940 | − pCtx->bLongTermRefFlag[d_idx][iCurTid] = false; | |
| 3941 | − } | |
| 3942 | − else | |
| 3943 | − { | |
| 3944 | − WelsExchangeSpatialPictures( &pCtx->pSpatialPic[d_idx][pCtx->uiSpatialLayersInTemporal[d_idx]-1], &pCtx->pSpatialPic[d_idx][iCurTid] ); | |
| 3945 | − } | |
| 3946 | − } | |
| 3947 | − | |
| 3948 | − if ( pSvcParam->bEnableLongTermReference && ((pCtx->pLtr[pCtx->uiDependencyId].bLTRMarkingFlag && (pCtx->pLtr[pCtx->uiDependencyId].iLTRMarkMode == LTR_DIRECT_MARK)) || eFrameType == WELS_FRAME_TYPE_IDR)) | |
| 3949 | − { | |
| 3950 | − pCtx->bLongTermRefFlag[d_idx][iCurTid] = true; | |
| 3951 | − } | |
| 3952 | − } | |
| 3953 | − | |
| 3954 | −#if defined(MT_ENABLED) && defined(MT_DEBUG) | |
| 3955 | − TrackSliceConsumeTime( pCtx, did_list, iSpatialNum ); | |
| 3956 | −#endif//MT_ENABLED && MT_DEBUG | |
| 3957 | − | |
| 3958 | −#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN) | |
| 3959 | − if ( pSvcParam->iMultipleThreadIdc > 1 && did_list[0] == BASE_DEPENDENCY_ID | |
| 3960 | − && pSvcParam->sDependencyLayers[0].sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE && pSvcParam->iMultipleThreadIdc >= pSvcParam->sDependencyLayers[0].sMso.sSliceArgument.iSliceNum | |
| 3961 | − && pSvcParam->sDependencyLayers[did_list[iSpatialNum-1]].sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE && pSvcParam->iMultipleThreadIdc >= pSvcParam->sDependencyLayers[did_list[iSpatialNum-1]].sMso.sSliceArgument.iSliceNum ) | |
| 3962 | − { | |
| 3963 | − AdjustBaseLayer( pCtx ); | |
| 3964 | − } | |
| 3965 | −#endif//DYNAMIC_SLICE_ASSIGN | |
| 3966 | − | |
| 3967 | −#ifdef ENABLE_FRAME_DUMP | |
| 3968 | − DumpRecFrame( fsnr, &pSvcParam->sDependencyLayers[pSvcParam->iNumDependencyLayer-1].sRecFileName[0] ); // pDecPic: final reconstruction output | |
| 3969 | −#endif//ENABLE_FRAME_DUMP | |
| 3970 | − | |
| 3971 | − ++ pCtx->iCodingIndex; | |
| 3972 | − pCtx->eLastNalPriority = eNalRefIdc; | |
| 3973 | − pFbi->iLayerNum = iLayerNum; | |
| 3974 | − | |
| 3975 | −#if defined(X86_ASM) | |
| 3976 | − WelsEmms(); | |
| 3977 | −#endif //X86_ASM | |
| 3978 | − | |
| 3979 | − return eFrameType; | |
| 3980 | −} | |
| 3981 | − | |
| 3982 | −/*! | |
| 3983 | − * \brief Wels SVC encoder parameters adjustment | |
| 3984 | − * SVC adjustment results in new requirement in memory blocks adjustment | |
| 3985 | − */ | |
| 3986 | −int32_t WelsEncoderParamAdjust( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pNewParam ) | |
| 3987 | −{ | |
| 3988 | − SWelsSvcCodingParam *pOldParam = NULL; | |
| 3989 | − int32_t iReturn = 0; | |
| 3990 | − int8_t iIndexD= 0; | |
| 3991 | − bool_t bNeedReset = false; | |
| 3992 | − | |
| 3993 | − if ( NULL == ppCtx || NULL == *ppCtx || NULL == pNewParam ) return 1; | |
| 3994 | − | |
| 3995 | − /* Check validation in new parameters */ | |
| 3996 | − iReturn = ParamValidationExt( pNewParam ); | |
| 3997 | − if ( iReturn != 0 ) return iReturn; | |
| 3998 | − | |
| 3999 | − pOldParam = (*ppCtx)->pSvcParam; | |
| 4000 | − | |
| 4001 | − /* Decide whether need reset for IDR frame based on adjusting prarameters changed */ | |
| 4002 | − /* Temporal levels, spatial settings and/ or quality settings changed need update parameter sets related. */ | |
| 4003 | − bNeedReset = (pOldParam == NULL ) || | |
| 4004 | − (pOldParam->iNumTemporalLayer != pNewParam->iNumTemporalLayer) || | |
| 4005 | − (pOldParam->uiGopSize != pNewParam->uiGopSize) || | |
| 4006 | − (pOldParam->iNumDependencyLayer != pNewParam->iNumDependencyLayer) || | |
| 4007 | − (pOldParam->iDecompStages != pNewParam->iDecompStages) || | |
| 4008 | − (pOldParam->iActualPicWidth != pNewParam->iActualPicWidth || pOldParam->iActualPicHeight != pNewParam->iActualPicHeight) || | |
| 4009 | − (pOldParam->SUsedPicRect.iWidth != pNewParam->SUsedPicRect.iWidth || pOldParam->SUsedPicRect.iHeight != pNewParam->SUsedPicRect.iHeight) || | |
| 4010 | − (pOldParam->bEnableLongTermReference != pNewParam->bEnableLongTermReference); | |
| 4011 | − if ( !bNeedReset ){ // Check its picture resolutions/quality settings respectively in each dependency layer | |
| 4012 | − iIndexD = 0; | |
| 4013 | − assert( pOldParam->iNumDependencyLayer == pNewParam->iNumDependencyLayer ); | |
| 4014 | − do | |
| 4015 | − { | |
| 4016 | − const SDLayerParam *kpOldDlp = &pOldParam->sDependencyLayers[iIndexD]; | |
| 4017 | − const SDLayerParam *kpNewDlp = &pNewParam->sDependencyLayers[iIndexD]; | |
| 4018 | − float fT1 = .0f; | |
| 4019 | − float fT2 = .0f; | |
| 4020 | − | |
| 4021 | − // check frame size settings | |
| 4022 | − if ( kpOldDlp->iFrameWidth != kpNewDlp->iFrameWidth || | |
| 4023 | − kpOldDlp->iFrameHeight != kpNewDlp->iFrameHeight || | |
| 4024 | − kpOldDlp->iActualWidth != kpNewDlp->iActualWidth || | |
| 4025 | − kpOldDlp->iActualHeight != kpNewDlp->iActualHeight ){ | |
| 4026 | − bNeedReset = true; | |
| 4027 | − break; | |
| 4028 | − } | |
| 4029 | − | |
| 4030 | − if ( kpOldDlp->sMso.uiSliceMode != kpNewDlp->sMso.uiSliceMode || | |
| 4031 | − kpOldDlp->sMso.sSliceArgument.iSliceNum != kpNewDlp->sMso.sSliceArgument.iSliceNum ) | |
| 4032 | − { | |
| 4033 | − bNeedReset = true; | |
| 4034 | − break; | |
| 4035 | − } | |
| 4036 | − | |
| 4037 | − // check frame rate | |
| 4038 | − // we can not check whether corresponding fFrameRate is equal or not, | |
| 4039 | − // only need to check d_max/d_min and max_fr/d_max whether it is equal or not | |
| 4040 | − if ( kpNewDlp->fInputFrameRate > EPSN && kpOldDlp->fInputFrameRate > EPSN ) | |
| 4041 | − fT1 = kpNewDlp->fOutputFrameRate/kpNewDlp->fInputFrameRate - kpOldDlp->fOutputFrameRate/kpOldDlp->fInputFrameRate; | |
| 4042 | − if ( kpNewDlp->fOutputFrameRate > EPSN && kpOldDlp->fOutputFrameRate > EPSN ) | |
| 4043 | − fT2 = pNewParam->fMaxFrameRate/kpNewDlp->fOutputFrameRate - pOldParam->fMaxFrameRate/kpOldDlp->fOutputFrameRate; | |
| 4044 | − if ( fT1 > EPSN || fT1 < -EPSN || fT2 > EPSN || fT2 < -EPSN ) | |
| 4045 | − { | |
| 4046 | − bNeedReset = true; | |
| 4047 | − break; | |
| 4048 | − } | |
| 4049 | − | |
| 4050 | − if ( kpOldDlp->iHighestTemporalId != kpNewDlp->iHighestTemporalId ) | |
| 4051 | − { | |
| 4052 | − bNeedReset = true; | |
| 4053 | − break; | |
| 4054 | − } | |
| 4055 | − | |
| 4056 | − ++ iIndexD; | |
| 4057 | − } while (iIndexD < pOldParam->iNumDependencyLayer); | |
| 4058 | − } | |
| 4059 | − | |
| 4060 | − if ( bNeedReset ){ | |
| 4061 | − SParaSetOffsetVariable sTmpPsoVariable[PARA_SET_TYPE]; | |
| 4062 | − uint16_t uiTmpIdrPicId;//this is for LTR! | |
| 4063 | − memcpy( sTmpPsoVariable, (*ppCtx)->sPSOVector.sParaSetOffsetVariable, (PARA_SET_TYPE)*sizeof(SParaSetOffsetVariable) );// confirmed_safe_unsafe_usage | |
| 4064 | − uiTmpIdrPicId = (*ppCtx)->sPSOVector.uiIdrPicId; | |
| 4065 | − | |
| 4066 | − WelsUninitEncoderExt( ppCtx ); | |
| 4067 | − | |
| 4068 | − /* Update new parameters */ | |
| 4069 | − if ( WelsInitEncoderExt( ppCtx, pNewParam ) ) | |
| 4070 | − return 1; | |
| 4071 | − | |
| 4072 | − // reset the scaled spatial picture size | |
| 4073 | − (*ppCtx)->pVpp->WelsPreprocessReset(*ppCtx); | |
| 4074 | − //if WelsInitEncoderExt succeed | |
| 4075 | − | |
| 4076 | − //for FLEXIBLE_PARASET_ID | |
| 4077 | − memcpy( (*ppCtx)->sPSOVector.sParaSetOffsetVariable, sTmpPsoVariable, (PARA_SET_TYPE)*sizeof(SParaSetOffsetVariable) );// confirmed_safe_unsafe_usage | |
| 4078 | − (*ppCtx)->sPSOVector.uiIdrPicId = uiTmpIdrPicId; | |
| 4079 | − } | |
| 4080 | − else{ | |
| 4081 | − /* maybe adjustment introduced in bitrate or little settings adjustment and so on.. */ | |
| 4082 | − pNewParam->iNumRefFrame = WELS_CLIP3(pNewParam->iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM); | |
| 4083 | − pNewParam->iLoopFilterDisableIdc = WELS_CLIP3(pNewParam->iLoopFilterDisableIdc, 0, 6); | |
| 4084 | − pNewParam->iLoopFilterAlphaC0Offset = WELS_CLIP3(pNewParam->iLoopFilterAlphaC0Offset, -6, 6); | |
| 4085 | − pNewParam->iLoopFilterBetaOffset = WELS_CLIP3(pNewParam->iLoopFilterBetaOffset, -6, 6); | |
| 4086 | − pNewParam->iInterLayerLoopFilterDisableIdc = WELS_CLIP3(pNewParam->iInterLayerLoopFilterDisableIdc, 0, 6); | |
| 4087 | − pNewParam->iInterLayerLoopFilterAlphaC0Offset = WELS_CLIP3(pNewParam->iInterLayerLoopFilterAlphaC0Offset, -6, 6); | |
| 4088 | − pNewParam->iInterLayerLoopFilterBetaOffset = WELS_CLIP3(pNewParam->iInterLayerLoopFilterBetaOffset, -6, 6); | |
| 4089 | − pNewParam->fMaxFrameRate = WELS_CLIP3(pNewParam->fMaxFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE); | |
| 4090 | − | |
| 4091 | − // we can not use direct struct based memcpy due some fields need keep unchanged as before | |
| 4092 | − pOldParam->fMaxFrameRate = pNewParam->fMaxFrameRate; // maximal frame rate [Hz / fps] | |
| 4093 | − pOldParam->iInputCsp = pNewParam->iInputCsp; // color space of input sequence | |
| 4094 | − pOldParam->uiIntraPeriod = pNewParam->uiIntraPeriod; // intra period (multiple of GOP size as desired) | |
| 4095 | − pOldParam->bEnableSpsPpsIdAddition = pNewParam->bEnableSpsPpsIdAddition; | |
| 4096 | − pOldParam->bPrefixNalAddingCtrl = pNewParam->bPrefixNalAddingCtrl; | |
| 4097 | − pOldParam->iNumRefFrame = pNewParam->iNumRefFrame; // number of reference frame used | |
| 4098 | − | |
| 4099 | − /* denoise control */ | |
| 4100 | − pOldParam->bEnableDenoise = pNewParam->bEnableDenoise; | |
| 4101 | − | |
| 4102 | − /* background detection control */ | |
| 4103 | − pOldParam->bEnableBackgroundDetection = pNewParam->bEnableBackgroundDetection; | |
| 4104 | − | |
| 4105 | − /* adaptive quantization control */ | |
| 4106 | − pOldParam->bEnableAdaptiveQuant = pNewParam->bEnableAdaptiveQuant; | |
| 4107 | − | |
| 4108 | − /* int32_t term reference control */ | |
| 4109 | − pOldParam->bEnableLongTermReference = pNewParam->bEnableLongTermReference; | |
| 4110 | − pOldParam->uiLtrMarkPeriod = pNewParam->uiLtrMarkPeriod; | |
| 4111 | − | |
| 4112 | − // keep below values unchanged as before | |
| 4113 | − pOldParam->bEnableSSEI = pNewParam->bEnableSSEI; | |
| 4114 | − pOldParam->bEnableFrameCroppingFlag = pNewParam->bEnableFrameCroppingFlag; // enable frame cropping flag | |
| 4115 | − | |
| 4116 | − /* Motion search */ | |
| 4117 | − | |
| 4118 | − /* Deblocking loop filter */ | |
| 4119 | − pOldParam->iLoopFilterDisableIdc = pNewParam->iLoopFilterDisableIdc; // 0: on, 1: off, 2: on except for slice boundaries | |
| 4120 | − pOldParam->iLoopFilterAlphaC0Offset = pNewParam->iLoopFilterAlphaC0Offset;// AlphaOffset: valid range [-6, 6], default 0 | |
| 4121 | − pOldParam->iLoopFilterBetaOffset = pNewParam->iLoopFilterBetaOffset; // BetaOffset: valid range [-6, 6], default 0 | |
| 4122 | − pOldParam->iInterLayerLoopFilterDisableIdc = pNewParam->iInterLayerLoopFilterDisableIdc; // Employed based upon inter-layer, same comment as above | |
| 4123 | − pOldParam->iInterLayerLoopFilterAlphaC0Offset = pNewParam->iInterLayerLoopFilterAlphaC0Offset; // InterLayerLoopFilterAlphaC0Offset | |
| 4124 | − pOldParam->iInterLayerLoopFilterBetaOffset = pNewParam->iInterLayerLoopFilterBetaOffset; // InterLayerLoopFilterBetaOffset | |
| 4125 | − | |
| 4126 | − /* Rate Control */ | |
| 4127 | − pOldParam->bEnableRc = pNewParam->bEnableRc; | |
| 4128 | − pOldParam->iRCMode = pNewParam->iRCMode; | |
| 4129 | − pOldParam->iTargetBitrate = pNewParam->iTargetBitrate; // overall target bitrate introduced in RC module | |
| 4130 | − pOldParam->iPaddingFlag = pNewParam->iPaddingFlag; | |
| 4131 | − | |
| 4132 | − /* Layer definition */ | |
| 4133 | − pOldParam->bPrefixNalAddingCtrl = pNewParam->bPrefixNalAddingCtrl; | |
| 4134 | − | |
| 4135 | − // d | |
| 4136 | − iIndexD = 0; | |
| 4137 | − do | |
| 4138 | − { | |
| 4139 | − SDLayerParam *pOldDlp = &pOldParam->sDependencyLayers[iIndexD]; | |
| 4140 | − SDLayerParam *pNewDlp = &pNewParam->sDependencyLayers[iIndexD]; | |
| 4141 | − | |
| 4142 | − pOldDlp->fInputFrameRate = pNewDlp->fInputFrameRate; // input frame rate | |
| 4143 | − pOldDlp->fOutputFrameRate = pNewDlp->fOutputFrameRate; // output frame rate | |
| 4144 | − pOldDlp->iSpatialBitrate = pNewDlp->iSpatialBitrate; | |
| 4145 | − | |
| 4146 | − pOldDlp->uiProfileIdc = pNewDlp->uiProfileIdc; // value of profile IDC (0 for auto-detection) | |
| 4147 | − | |
| 4148 | − /* Derived variants below */ | |
| 4149 | − pOldDlp->iTemporalResolution = pNewDlp->iTemporalResolution; | |
| 4150 | − pOldDlp->iDecompositionStages = pNewDlp->iDecompositionStages; | |
| 4151 | − | |
| 4152 | − memcpy(pOldDlp->uiCodingIdx2TemporalId, pNewDlp->uiCodingIdx2TemporalId, sizeof(pOldDlp->uiCodingIdx2TemporalId)); // confirmed_safe_unsafe_usage | |
| 4153 | − | |
| 4154 | − ++ iIndexD; | |
| 4155 | − } while (iIndexD < pOldParam->iNumDependencyLayer); | |
| 4156 | − } | |
| 4157 | − | |
| 4158 | − /* Any else initialization/reset for rate control here? */ | |
| 4159 | − | |
| 4160 | − return 0; | |
| 4161 | −} | |
| 4162 | − | |
| 4163 | − | |
| 4164 | −int32_t WelsCodeOnePicPartition( sWelsEncCtx *pCtx, | |
| 4165 | − SLayerBSInfo *pLayerBsInfo, | |
| 4166 | − int32_t *pNalIdxInLayer, | |
| 4167 | − int32_t* pLayerSize, | |
| 4168 | − int32_t iFirstMbInPartition, // first mb inclusive in partition | |
| 4169 | − int32_t iEndMbInPartition, // end mb exclusive in partition | |
| 4170 | − int32_t iStartSliceIdx | |
| 4171 | − ) | |
| 4172 | −{ | |
| 4173 | − | |
| 4174 | − SDqLayer * pCurLayer = pCtx->pCurDqLayer; | |
| 4175 | − SSliceCtx * pSliceCtx = pCurLayer->pSliceEncCtx; | |
| 4176 | − int32_t iNalLen[MAX_NAL_UNITS_IN_LAYER] = {0}; | |
| 4177 | − int32_t iNalIdxInLayer = *pNalIdxInLayer; | |
| 4178 | − int32_t iSliceIdx = iStartSliceIdx; | |
| 4179 | − const int32_t kiSliceStep = pCtx->iActiveThreadsNum; | |
| 4180 | − const int32_t kiPartitionId = iStartSliceIdx % kiSliceStep; | |
| 4181 | − int32_t iPartitionBsSize = 0; | |
| 4182 | − int32_t iAnyMbLeftInPartition= iEndMbInPartition - iFirstMbInPartition; | |
| 4183 | − const EWelsNalUnitType keNalType = pCtx->eNalType; | |
| 4184 | − const EWelsNalRefIdc keNalRefIdc = pCtx->eNalPriority; | |
| 4185 | − const bool_t kbNeedPrefix = pCtx->bNeedPrefixNalFlag; | |
| 4186 | − | |
| 4187 | − //init | |
| 4188 | − { | |
| 4189 | − pSliceCtx->pFirstMbInSlice[iSliceIdx] = iFirstMbInPartition; | |
| 4190 | − pCurLayer->pNumSliceCodedOfPartition[kiPartitionId] = 1; // one slice per partition intialized, dynamic slicing inside | |
| 4191 | − pCurLayer->pLastMbIdxOfPartition[kiPartitionId] = iEndMbInPartition-1; | |
| 4192 | − } | |
| 4193 | − pCurLayer->pLastCodedMbIdxOfPartition[kiPartitionId] = 0; | |
| 4194 | − | |
| 4195 | − while ( iAnyMbLeftInPartition > 0 ) | |
| 4196 | − { | |
| 4197 | − int32_t iSliceSize = 0; | |
| 4198 | − | |
| 4199 | − if ( iSliceIdx >= pSliceCtx->iMaxSliceNumConstraint ) // insufficient memory in pSliceInLayer[] | |
| 4200 | − { | |
| 4201 | − // TODO: need exception handler for not large enough of MAX_SLICES_NUM related memory usage | |
| 4202 | − // No idea about its solution due MAX_SLICES_NUM is fixed lenght in relevent pData structure | |
| 4203 | − return 1; | |
| 4204 | − } | |
| 4205 | − | |
| 4206 | − if ( kbNeedPrefix ) | |
| 4207 | − { | |
| 4208 | − iPartitionBsSize += AddPrefixNal( pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, keNalType, keNalRefIdc ); | |
| 4209 | − } | |
| 4210 | − | |
| 4211 | − WelsLoadNal( pCtx->pOut, keNalType, keNalRefIdc ); | |
| 4212 | − WelsCodeOneSlice( pCtx, iSliceIdx, keNalType ); | |
| 4213 | − WelsUnloadNal( pCtx->pOut ); | |
| 4214 | − | |
| 4215 | − iSliceSize = WelsEncodeNalExt( &pCtx->pOut->sNalList[pCtx->pOut->iNalIndex-1], | |
| 4216 | − &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt, | |
| 4217 | − pCtx->pFrameBs + pCtx->iPosBsBuffer, | |
| 4218 | − &iNalLen[iNalIdxInLayer] ); | |
| 4219 | − pCtx->iPosBsBuffer += iSliceSize; | |
| 4220 | − iPartitionBsSize += iSliceSize; | |
| 4221 | − pLayerBsInfo->iNalLengthInByte[iNalIdxInLayer] = iSliceSize; | |
| 4222 | − | |
| 4223 | −#if defined(SLICE_INFO_OUTPUT) | |
| 4224 | − fprintf( stderr, | |
| 4225 | − "@slice=%-6d sliceType:%c idc:%d size:%-6d\n", | |
| 4226 | − iSliceIdx, | |
| 4227 | − (pCtx->eSliceType == P_SLICE ? 'P' : 'I'), | |
| 4228 | − eNalRefIdc, | |
| 4229 | − iSliceSize ); | |
| 4230 | −#endif//SLICE_INFO_OUTPUT | |
| 4231 | − | |
| 4232 | − ++ iNalIdxInLayer; | |
| 4233 | − iSliceIdx += kiSliceStep; //if uiSliceIdx is not continuous | |
| 4234 | − iAnyMbLeftInPartition = iEndMbInPartition - (1 + pCurLayer->pLastCodedMbIdxOfPartition[kiPartitionId]); | |
| 4235 | − } | |
| 4236 | − | |
| 4237 | − *pLayerSize = iPartitionBsSize; | |
| 4238 | − *pNalIdxInLayer = iNalIdxInLayer; | |
| 4239 | − | |
| 4240 | − // slice based packing??? | |
| 4241 | − pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER; | |
| 4242 | − pLayerBsInfo->uiSpatialId = pCtx->uiDependencyId; | |
| 4243 | − pLayerBsInfo->uiTemporalId = pCtx->uiTemporalId; | |
| 4244 | − pLayerBsInfo->uiQualityId = 0; | |
| 4245 | − pLayerBsInfo->uiPriorityId = 0; | |
| 4246 | − pLayerBsInfo->iNalCount = iNalIdxInLayer; | |
| 4247 | − | |
| 4248 | − return 0; | |
| 4249 | −} | |
| 4250 | −} // namespace WelsSVCEnc | |
| 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 encoder_ext.c | |
| 33 | + * | |
| 34 | + * \brief core encoder for SVC | |
| 35 | + * | |
| 36 | + * \date 7/24/2009 Created | |
| 37 | + * | |
| 38 | + ************************************************************************************* | |
| 39 | + */ | |
| 40 | +#include <string.h> | |
| 41 | +#include <stdlib.h> | |
| 42 | +#include <assert.h> | |
| 43 | + | |
| 44 | +#include "encoder.h" | |
| 45 | +#include "extern.h" | |
| 46 | +#include "encoder_context.h" | |
| 47 | +#include "typedefs.h" | |
| 48 | +#include "wels_const.h" | |
| 49 | +#include "wels_common_basis.h" | |
| 50 | +#include "codec_def.h" | |
| 51 | +#include "param_svc.h" | |
| 52 | +#include "cpu_core.h" | |
| 53 | +#include "cpu.h" | |
| 54 | +#include "utils.h" | |
| 55 | +#include "svc_enc_frame.h" | |
| 56 | +#include "svc_enc_golomb.h" | |
| 57 | +#include "svc_enc_slice_segment.h" | |
| 58 | +#include "au_set.h" | |
| 59 | +#include "picture_handle.h" | |
| 60 | +#include "codec_app_def.h" | |
| 61 | +#include "svc_base_layer_md.h" | |
| 62 | +#include "svc_encode_slice.h" | |
| 63 | +#include "decode_mb_aux.h" | |
| 64 | +#include "deblocking.h" | |
| 65 | +#include "rc.h" | |
| 66 | +#include "ref_list_mgr_svc.h" | |
| 67 | +#include "md.h" | |
| 68 | +#include "ls_defines.h" | |
| 69 | +#include "set_mb_syn_cavlc.h" | |
| 70 | +#include "crt_util_safe_x.h" // Safe CRT routines like utils for cross platforms | |
| 71 | +#include "array_stack_align.h" | |
| 72 | +// for MT, 4/22/2010 | |
| 73 | +#include "slice_multi_threading.h" | |
| 74 | +#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 75 | +#include "measure_time.h" | |
| 76 | +#endif//DYNAMIC_SLICE_ASSIGN | |
| 77 | + | |
| 78 | +namespace WelsSVCEnc { | |
| 79 | + | |
| 80 | + | |
| 81 | +int32_t WelsCodeOnePicPartition (sWelsEncCtx* pCtx, | |
| 82 | + SLayerBSInfo* pLbi, | |
| 83 | + int32_t* pNalIdxInLayer, | |
| 84 | + int32_t* pLayerSize, | |
| 85 | + int32_t iFirstMbInPartition, // first mb inclusive in partition | |
| 86 | + int32_t iEndMbInPartition, // end mb exclusive in partition | |
| 87 | + int32_t iStartSliceIdx | |
| 88 | + ); | |
| 89 | + | |
| 90 | + | |
| 91 | +/*! | |
| 92 | + * \brief validate checking in parameter configuration | |
| 93 | + * \pParam pParam SWelsSvcCodingParam* | |
| 94 | + * \return successful - 0; otherwise none 0 for failed | |
| 95 | + */ | |
| 96 | +int32_t ParamValidation (SWelsSvcCodingParam* pCfg) { | |
| 97 | + float fMaxFrameRate = 0.0f; | |
| 98 | + const float fEpsn = 0.000001f; | |
| 99 | + int32_t i = 0; | |
| 100 | + int32_t iLastSpatialWidth = 0; | |
| 101 | + int32_t iLastSpatialHeight = 0; | |
| 102 | + float fLastFrameRateIn = 0.0f; | |
| 103 | + float fLastFrameRateOut = 0.0f; | |
| 104 | + SDLayerParam* pLastSpatialParam = NULL; | |
| 105 | + | |
| 106 | + assert (pCfg != NULL); | |
| 107 | + | |
| 108 | + for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) { | |
| 109 | + SDLayerParam* fDlp = &pCfg->sDependencyLayers[i]; | |
| 110 | + if (fDlp->fOutputFrameRate > fDlp->fInputFrameRate || (fDlp->fInputFrameRate >= -fEpsn | |
| 111 | + && fDlp->fInputFrameRate <= fEpsn) | |
| 112 | + || (fDlp->fOutputFrameRate >= -fEpsn && fDlp->fOutputFrameRate <= fEpsn)) { | |
| 113 | +#if defined (_DEBUG) | |
| 114 | + fprintf (stderr, "Invalid settings in input frame rate(%.6f) or output frame rate(%.6f) of layer #%d config file..\n", | |
| 115 | + fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i); | |
| 116 | +#endif | |
| 117 | + return 1; | |
| 118 | + } | |
| 119 | + if (UINT_MAX == GetLogFactor (fDlp->fOutputFrameRate, fDlp->fInputFrameRate)) { | |
| 120 | +#if defined (_DEBUG) | |
| 121 | + fprintf (stderr, | |
| 122 | + "Invalid settings in input frame rate(%.6f) and output frame rate(%.6f) of layer #%d config file: iResult of output frame rate divided by input frame rate should be power of 2(i.e,in/pOut=2^n)..\n", | |
| 123 | + fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i); | |
| 124 | +#endif | |
| 125 | + return 1; | |
| 126 | + } | |
| 127 | + } | |
| 128 | + | |
| 129 | + for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) { | |
| 130 | + SDLayerParam* fDlp = &pCfg->sDependencyLayers[i]; | |
| 131 | + if (fDlp->fInputFrameRate > fMaxFrameRate) | |
| 132 | + fMaxFrameRate = fDlp->fInputFrameRate; | |
| 133 | + } | |
| 134 | + | |
| 135 | + if (fMaxFrameRate > fEpsn && (fMaxFrameRate - pCfg->fMaxFrameRate > fEpsn | |
| 136 | + || fMaxFrameRate - pCfg->fMaxFrameRate < -fEpsn)) { | |
| 137 | + pCfg->fMaxFrameRate = fMaxFrameRate; | |
| 138 | + } | |
| 139 | + | |
| 140 | + for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) { | |
| 141 | + SDLayerParam* fDlp = &pCfg->sDependencyLayers[i]; | |
| 142 | + | |
| 143 | + pLastSpatialParam = fDlp; | |
| 144 | + iLastSpatialWidth = fDlp->iFrameWidth; | |
| 145 | + iLastSpatialHeight = fDlp->iFrameHeight; | |
| 146 | + fLastFrameRateIn = fDlp->fInputFrameRate; | |
| 147 | + fLastFrameRateOut = fDlp->fOutputFrameRate; | |
| 148 | + } | |
| 149 | + | |
| 150 | + return 0; | |
| 151 | +} | |
| 152 | + | |
| 153 | +int32_t ParamValidationExt (void* pParam) { | |
| 154 | + SWelsSvcCodingParam* pCodingParam = (SWelsSvcCodingParam*)pParam; | |
| 155 | + int8_t i = 0; | |
| 156 | + int32_t iIdx = 0; | |
| 157 | + | |
| 158 | + assert (pCodingParam != NULL); | |
| 159 | + if (NULL == pCodingParam) | |
| 160 | + return 1; | |
| 161 | + | |
| 162 | + if (pCodingParam->iNumDependencyLayer < 1 || pCodingParam->iNumDependencyLayer > MAX_DEPENDENCY_LAYER) { | |
| 163 | +#if defined (_DEBUG) | |
| 164 | + fprintf (stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumDependencyLayer: %d!\n", | |
| 165 | + pCodingParam->iNumDependencyLayer); | |
| 166 | +#endif//#if _DEBUG | |
| 167 | + | |
| 168 | + return 1; | |
| 169 | + } | |
| 170 | + | |
| 171 | + if (pCodingParam->iNumTemporalLayer < 1 || pCodingParam->iNumTemporalLayer > MAX_TEMPORAL_LEVEL) { | |
| 172 | +#if defined (_DEBUG) | |
| 173 | + fprintf (stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumTemporalLayer: %d!\n", | |
| 174 | + pCodingParam->iNumTemporalLayer); | |
| 175 | +#endif//#if _DEBUG | |
| 176 | + return 1; | |
| 177 | + } | |
| 178 | + | |
| 179 | + if (pCodingParam->uiGopSize < 1 || pCodingParam->uiGopSize > MAX_GOP_SIZE) { | |
| 180 | +#if defined (_DEBUG) | |
| 181 | + fprintf (stderr, "ParamValidationExt(), monitor invalid pCodingParam->uiGopSize: %d!\n", pCodingParam->uiGopSize); | |
| 182 | +#endif//#if _DEBUG | |
| 183 | + return 1; | |
| 184 | + } | |
| 185 | + | |
| 186 | + | |
| 187 | + if (pCodingParam->uiIntraPeriod && pCodingParam->uiIntraPeriod < pCodingParam->uiGopSize) { | |
| 188 | +#if defined (_DEBUG) | |
| 189 | + fprintf (stderr, | |
| 190 | + "ParamValidationExt(), uiIntraPeriod(%d) should be not less than that of uiGopSize(%d) or -1 specified!\n", | |
| 191 | + pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize); | |
| 192 | +#endif//#if _DEBUG | |
| 193 | + return 1; | |
| 194 | + } | |
| 195 | + | |
| 196 | + if (pCodingParam->uiIntraPeriod && (pCodingParam->uiIntraPeriod & (pCodingParam->uiGopSize - 1)) != 0) { | |
| 197 | +#if defined (_DEBUG) | |
| 198 | + fprintf (stderr, "ParamValidationExt(), uiIntraPeriod(%d) should be multiple of uiGopSize(%d) or -1 specified!\n", | |
| 199 | + pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize); | |
| 200 | +#endif//#if _DEBUG | |
| 201 | + return 1; | |
| 202 | + } | |
| 203 | + | |
| 204 | + | |
| 205 | +#ifdef MT_ENABLED | |
| 206 | + //about iMultipleThreadIdc, bDeblockingParallelFlag, iLoopFilterDisableIdc, & uiSliceMode | |
| 207 | + // (1) Single Thread | |
| 208 | + // if (THREAD==1)//single thread | |
| 209 | + // no parallel_deblocking: bDeblockingParallelFlag = 0; | |
| 210 | + // (2) Multi Thread: see uiSliceMode decision | |
| 211 | + if (pCodingParam->iMultipleThreadIdc == 1) { | |
| 212 | + //now is single thread. no parallel deblocking, set flag=0 | |
| 213 | + pCodingParam->bDeblockingParallelFlag = false; | |
| 214 | + } else { | |
| 215 | + pCodingParam->bDeblockingParallelFlag = true; | |
| 216 | + } | |
| 217 | +#else | |
| 218 | + pCodingParam->bDeblockingParallelFlag = false; | |
| 219 | +#endif//MT_ENABLED | |
| 220 | + | |
| 221 | + for (i = 0; i < pCodingParam->iNumDependencyLayer; ++ i) { | |
| 222 | + SDLayerParam* fDlp = &pCodingParam->sDependencyLayers[i]; | |
| 223 | + const int32_t kiPicWidth = fDlp->iFrameWidth; | |
| 224 | + const int32_t kiPicHeight = fDlp->iFrameHeight; | |
| 225 | + int32_t iMbWidth = 0; | |
| 226 | + int32_t iMbHeight = 0; | |
| 227 | + int32_t iMbNumInFrame = 0; | |
| 228 | + int32_t iMaxSliceNum = MAX_SLICES_NUM; | |
| 229 | + if (kiPicWidth <= 0 || kiPicHeight <= 0) { | |
| 230 | +#if defined (_DEBUG) | |
| 231 | + fprintf (stderr, "ParamValidationExt(), invalid %d x %d in dependency layer settings!\n", kiPicWidth, kiPicHeight); | |
| 232 | +#endif//#if _DEBUG | |
| 233 | + return 1; | |
| 234 | + } | |
| 235 | + if ((kiPicWidth & 0x0F) != 0 || (kiPicHeight & 0x0F) != 0) { | |
| 236 | +#if defined (_DEBUG) | |
| 237 | + fprintf (stderr, | |
| 238 | + "ParamValidationExt(), in layer #%d iWidth x iHeight(%d x %d) both should be multiple of 16, can not support with arbitrary size currently!\n", | |
| 239 | + i, kiPicWidth, kiPicHeight); | |
| 240 | +#endif//#if _DEBUG | |
| 241 | + return 1; | |
| 242 | + } | |
| 243 | + | |
| 244 | + if (fDlp->sMso.uiSliceMode >= SM_RESERVED) { | |
| 245 | +#if defined (_DEBUG) | |
| 246 | + fprintf (stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", fDlp->sMso.uiSliceMode); | |
| 247 | +#endif//#if _DEBUG | |
| 248 | + return 1; | |
| 249 | + } | |
| 250 | + | |
| 251 | + //check pSlice settings under multi-pSlice | |
| 252 | + if (kiPicWidth <= 16 && kiPicHeight <= 16) { | |
| 253 | + //only have one MB, set to single_slice | |
| 254 | + fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 255 | + } | |
| 256 | + switch (fDlp->sMso.uiSliceMode) { | |
| 257 | + case SM_SINGLE_SLICE: | |
| 258 | + fDlp->sMso.sSliceArgument.iSliceNum = 1; | |
| 259 | + fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | |
| 260 | + fDlp->sMso.sSliceArgument.iSliceNum = 0; | |
| 261 | + for (iIdx = 0; iIdx < MAX_SLICES_NUM; iIdx++) { | |
| 262 | + fDlp->sMso.sSliceArgument.uiSliceMbNum[iIdx] = 0; | |
| 263 | + } | |
| 264 | + break; | |
| 265 | + case SM_FIXEDSLCNUM_SLICE: { | |
| 266 | + fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | |
| 267 | + | |
| 268 | + iMbWidth = (kiPicWidth + 15) >> 4; | |
| 269 | + iMbHeight = (kiPicHeight + 15) >> 4; | |
| 270 | + iMbNumInFrame = iMbWidth * iMbHeight; | |
| 271 | + iMaxSliceNum = MAX_SLICES_NUM; | |
| 272 | + if (fDlp->sMso.sSliceArgument.iSliceNum <= 0 | |
| 273 | + || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum) { | |
| 274 | +#if defined (_DEBUG) | |
| 275 | + fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum); | |
| 276 | +#endif//#if _DEBUG | |
| 277 | + return 1; | |
| 278 | + } | |
| 279 | + if (fDlp->sMso.sSliceArgument.iSliceNum == 1) { | |
| 280 | +#if defined (_DEBUG) | |
| 281 | + fprintf (stderr, | |
| 282 | + "ParamValidationExt(), uiSliceNum(%d) you set for SM_FIXEDSLCNUM_SLICE, now turn to SM_SINGLE_SLICE type!\n", | |
| 283 | + fDlp->sMso.sSliceArgument.iSliceNum); | |
| 284 | +#endif//#if _DEBUG | |
| 285 | + fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 286 | + break; | |
| 287 | + } | |
| 288 | + if (pCodingParam->bEnableRc) { // multiple slices verify with gom | |
| 289 | + //check uiSliceNum | |
| 290 | + GomValidCheckSliceNum (iMbWidth, iMbHeight, (int32_t*)&fDlp->sMso.sSliceArgument.iSliceNum); | |
| 291 | + assert (fDlp->sMso.sSliceArgument.iSliceNum > 1); | |
| 292 | + //set uiSliceMbNum with current uiSliceNum | |
| 293 | + GomValidCheckSliceMbNum (iMbWidth, iMbHeight, &fDlp->sMso.sSliceArgument); | |
| 294 | + } else if (!CheckFixedSliceNumMultiSliceSetting (iMbNumInFrame, | |
| 295 | + &fDlp->sMso.sSliceArgument)) { // verify interleave mode settings | |
| 296 | + //check uiSliceMbNum with current uiSliceNum | |
| 297 | +#if defined (_DEBUG) | |
| 298 | + fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", | |
| 299 | + fDlp->sMso.sSliceArgument.uiSliceMbNum[0]); | |
| 300 | +#endif//#if _DEBUG | |
| 301 | + return 1; | |
| 302 | + } | |
| 303 | + // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting | |
| 304 | + if (iMbNumInFrame <= MIN_NUM_MB_PER_SLICE) { | |
| 305 | + fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 306 | + fDlp->sMso.sSliceArgument.iSliceNum = 1; | |
| 307 | + break; | |
| 308 | + } | |
| 309 | + } | |
| 310 | + break; | |
| 311 | + case SM_RASTER_SLICE: { | |
| 312 | + fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | |
| 313 | + | |
| 314 | + iMbWidth = (kiPicWidth + 15) >> 4; | |
| 315 | + iMbHeight = (kiPicHeight + 15) >> 4; | |
| 316 | + iMbNumInFrame = iMbWidth * iMbHeight; | |
| 317 | + iMaxSliceNum = MAX_SLICES_NUM; | |
| 318 | + if (fDlp->sMso.sSliceArgument.uiSliceMbNum[0] <= 0) { | |
| 319 | +#if defined (_DEBUG) | |
| 320 | + fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", | |
| 321 | + fDlp->sMso.sSliceArgument.uiSliceMbNum[0]); | |
| 322 | +#endif//#if _DEBUG | |
| 323 | + return 1; | |
| 324 | + } | |
| 325 | + | |
| 326 | + if (!CheckRasterMultiSliceSetting (iMbNumInFrame, &fDlp->sMso.sSliceArgument)) { // verify interleave mode settings | |
| 327 | +#if defined (_DEBUG) | |
| 328 | + fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", | |
| 329 | + fDlp->sMso.sSliceArgument.uiSliceMbNum[0]); | |
| 330 | +#endif//#if _DEBUG | |
| 331 | + return 1; | |
| 332 | + } | |
| 333 | + if (fDlp->sMso.sSliceArgument.iSliceNum <= 0 | |
| 334 | + || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum) { // verify interleave mode settings | |
| 335 | +#if defined (_DEBUG) | |
| 336 | + fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) in SM_RASTER_SLICE settings!\n", | |
| 337 | + fDlp->sMso.sSliceArgument.iSliceNum); | |
| 338 | +#endif//#if _DEBUG | |
| 339 | + return 1; | |
| 340 | + } | |
| 341 | + if (fDlp->sMso.sSliceArgument.iSliceNum == 1) { | |
| 342 | +#if defined (_DEBUG) | |
| 343 | + fprintf (stderr, "ParamValidationExt(), pSlice setting for SM_RASTER_SLICE now turn to SM_SINGLE_SLICE!\n"); | |
| 344 | +#endif//#if _DEBUG | |
| 345 | + fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 346 | + break; | |
| 347 | + } | |
| 348 | +#ifdef MT_ENABLED | |
| 349 | + if (pCodingParam->bEnableRc && fDlp->sMso.sSliceArgument.iSliceNum > 1) { | |
| 350 | +#if defined (_DEBUG) | |
| 351 | + fprintf (stderr, "ParamValidationExt(), WARNING: GOM based RC do not support SM_RASTER_SLICE!\n"); | |
| 352 | +#endif//#if _DEBUG | |
| 353 | + } | |
| 354 | +#endif | |
| 355 | + // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting | |
| 356 | + if (iMbNumInFrame <= MIN_NUM_MB_PER_SLICE) { | |
| 357 | + fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 358 | + fDlp->sMso.sSliceArgument.iSliceNum = 1; | |
| 359 | + break; | |
| 360 | + } | |
| 361 | + } | |
| 362 | + break; | |
| 363 | + case SM_ROWMB_SLICE: { | |
| 364 | + fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | |
| 365 | + | |
| 366 | + iMbWidth = (kiPicWidth + 15) >> 4; | |
| 367 | + iMbHeight = (kiPicHeight + 15) >> 4; | |
| 368 | + iMaxSliceNum = MAX_SLICES_NUM; | |
| 369 | + if (iMbHeight > iMaxSliceNum) { | |
| 370 | +#if defined (_DEBUG) | |
| 371 | + fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings more than MAX!\n", iMbHeight); | |
| 372 | +#endif//#if _DEBUG | |
| 373 | + return 1; | |
| 374 | + } | |
| 375 | + fDlp->sMso.sSliceArgument.iSliceNum = iMbHeight; | |
| 376 | + | |
| 377 | + if (fDlp->sMso.sSliceArgument.iSliceNum <= 0) { | |
| 378 | +#if defined (_DEBUG) | |
| 379 | + fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum); | |
| 380 | +#endif//#if _DEBUG | |
| 381 | + return 1; | |
| 382 | + } | |
| 383 | + if (!CheckRowMbMultiSliceSetting (iMbWidth, &fDlp->sMso.sSliceArgument)) { // verify interleave mode settings | |
| 384 | +#if defined (_DEBUG) | |
| 385 | + fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", | |
| 386 | + fDlp->sMso.sSliceArgument.uiSliceMbNum[0]); | |
| 387 | +#endif//#if _DEBUG | |
| 388 | + return 1; | |
| 389 | + } | |
| 390 | + } | |
| 391 | + break; | |
| 392 | + case SM_DYN_SLICE: { | |
| 393 | + iMbWidth = (kiPicWidth + 15) >> 4; | |
| 394 | + iMbHeight = (kiPicHeight + 15) >> 4; | |
| 395 | + if (fDlp->sMso.sSliceArgument.uiSliceSizeConstraint <= 0) { | |
| 396 | +#if defined (_DEBUG) | |
| 397 | + fprintf (stderr, "ParamValidationExt(), invalid iSliceSize (%d) settings!\n", | |
| 398 | + fDlp->sMso.sSliceArgument.uiSliceSizeConstraint); | |
| 399 | +#endif//#if _DEBUG | |
| 400 | + return 1; | |
| 401 | + } | |
| 402 | + // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting | |
| 403 | + if (iMbWidth * iMbHeight <= MIN_NUM_MB_PER_SLICE) { | |
| 404 | + fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | |
| 405 | + fDlp->sMso.sSliceArgument.iSliceNum = 1; | |
| 406 | + break; | |
| 407 | + } | |
| 408 | + } | |
| 409 | + break; | |
| 410 | + default: { | |
| 411 | + | |
| 412 | +#if defined (_DEBUG) | |
| 413 | + fprintf (stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", | |
| 414 | + pCodingParam->sDependencyLayers[0].sMso.uiSliceMode); | |
| 415 | +#endif//#if _DEBUG | |
| 416 | + return 1; | |
| 417 | + | |
| 418 | + } | |
| 419 | + break; | |
| 420 | + } | |
| 421 | + } | |
| 422 | + | |
| 423 | + return ParamValidation (pCodingParam); | |
| 424 | +} | |
| 425 | + | |
| 426 | +/*! | |
| 427 | + * \brief acquire count number of layers and NALs based on configurable paramters dependency | |
| 428 | + * \pParam pCtx sWelsEncCtx* | |
| 429 | + * \pParam pParam SWelsSvcCodingParam* | |
| 430 | + * \pParam pCountLayers pointer of count number of layers indeed | |
| 431 | + * \pParam iCountNals pointer of count number of nals indeed | |
| 432 | + * \return 0 - successful; otherwise failed | |
| 433 | + */ | |
| 434 | +static inline int32_t AcquireLayersNals (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pParam, int32_t* pCountLayers, | |
| 435 | + int32_t* pCountNals) { | |
| 436 | + int32_t iCountNumLayers = 0; | |
| 437 | + int32_t iCountNumNals = 0; | |
| 438 | + int32_t iNumDependencyLayers = 0; | |
| 439 | + int32_t iDIndex = 0; | |
| 440 | +#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 441 | + int32_t iNumLayersPack = 0; | |
| 442 | +#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | |
| 443 | + | |
| 444 | + if (NULL == pParam || NULL == ppCtx || NULL == *ppCtx) | |
| 445 | + return 1; | |
| 446 | + | |
| 447 | + iNumDependencyLayers = pParam->iNumDependencyLayer; | |
| 448 | + | |
| 449 | + do { | |
| 450 | + SDLayerParam* pDLayer = &pParam->sDependencyLayers[iDIndex]; | |
| 451 | +// pDLayer->ptr_cfg = pParam; | |
| 452 | + int32_t iOrgNumNals = iCountNumNals; | |
| 453 | + | |
| 454 | + //Note: Sep. 2010 | |
| 455 | + //Review this part and suggest no change, since the memory over-use | |
| 456 | + //(1) counts little to the overall performance | |
| 457 | + //(2) should not be critial even under mobile case | |
| 458 | + if (SM_DYN_SLICE == pDLayer->sMso.uiSliceMode) { | |
| 459 | + iCountNumNals += MAX_SLICES_NUM; | |
| 460 | + // plus prefix NALs | |
| 461 | + if (iDIndex == 0) | |
| 462 | + iCountNumNals += MAX_SLICES_NUM; | |
| 463 | + // MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME ensured at svc_enc_slice_segment.h | |
| 464 | +#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 465 | + assert (MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME); | |
| 466 | + // iNumLayersPack += MAX_SLICES_NUM; // do not count it for dynamic slicing mode | |
| 467 | +#else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER | |
| 468 | + assert (iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER); | |
| 469 | +#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | |
| 470 | + } else { /*if ( SM_SINGLE_SLICE != pDLayer->sMso.uiSliceMode )*/ | |
| 471 | + const int32_t kiNumOfSlice = GetInitialSliceNum ((pDLayer->iFrameWidth + 0x0f) >> 4, | |
| 472 | + (pDLayer->iFrameHeight + 0x0f) >> 4, | |
| 473 | + &pDLayer->sMso); | |
| 474 | + | |
| 475 | + // NEED check iCountNals value in case multiple slices is used | |
| 476 | + iCountNumNals += kiNumOfSlice; // for pSlice VCL NALs | |
| 477 | + // plus prefix NALs | |
| 478 | + if (iDIndex == 0) | |
| 479 | + iCountNumNals += kiNumOfSlice; | |
| 480 | +#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 481 | + assert (num_of_slice <= MAX_SLICES_NUM && MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME); | |
| 482 | + iNumLayersPack += num_of_slice; | |
| 483 | +#else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER | |
| 484 | + assert (iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER); | |
| 485 | +#endif//MT_ENALBED && PACKING_ONE_SLICE_PER_LAYER | |
| 486 | + if (kiNumOfSlice > MAX_SLICES_NUM) { | |
| 487 | + WelsLog (*ppCtx, WELS_LOG_ERROR, | |
| 488 | + "AcquireLayersNals(), num_of_slice(%d) > MAX_SLICES_NUM(%d) per (iDid= %d, qid= %d) settings!\n", | |
| 489 | + kiNumOfSlice, MAX_SLICES_NUM, iDIndex, 0); | |
| 490 | + return 1; | |
| 491 | + } | |
| 492 | + } | |
| 493 | +#if !defined(MT_ENABLED) || !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 494 | + if (iCountNumNals - iOrgNumNals > MAX_NAL_UNITS_IN_LAYER) { | |
| 495 | + WelsLog (*ppCtx, WELS_LOG_ERROR, | |
| 496 | + "AcquireLayersNals(), num_of_nals(%d) > MAX_NAL_UNITS_IN_LAYER(%d) per (iDid= %d, qid= %d) settings!\n", | |
| 497 | + (iCountNumNals - iOrgNumNals), MAX_NAL_UNITS_IN_LAYER, iDIndex, 0); | |
| 498 | + return 1; | |
| 499 | + } | |
| 500 | +#endif//!MT_ENABLED) || !PACKING_ONE_SLICE_PER_LAYER | |
| 501 | + | |
| 502 | + iCountNumLayers ++; | |
| 503 | + | |
| 504 | + ++ iDIndex; | |
| 505 | + } while (iDIndex < iNumDependencyLayers); | |
| 506 | + | |
| 507 | + iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers << 1) + | |
| 508 | + iCountNumLayers; // plus iCountNumLayers for reserved application | |
| 509 | +#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 510 | + iNumLayersPack += 1 + iNumDependencyLayers + (iCountNumLayers << 1); | |
| 511 | +#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | |
| 512 | + | |
| 513 | + // to check number of layers / nals / slices dependencies, 12/8/2010 | |
| 514 | +#if !defined(MT_ENABLED) | |
| 515 | + if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) { | |
| 516 | + WelsLog (*ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", | |
| 517 | + iCountNumLayers, MAX_LAYER_NUM_OF_FRAME); | |
| 518 | + return 1; | |
| 519 | + } | |
| 520 | +#else//MT_ENABLED | |
| 521 | +#if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 522 | + if (iNumLayersPack > MAX_LAYER_NUM_OF_FRAME) { | |
| 523 | + WelsLog (*ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), num_layers_pack_overall(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", | |
| 524 | + iNumLayersPack, MAX_LAYER_NUM_OF_FRAME); | |
| 525 | + return 1; | |
| 526 | + } | |
| 527 | +#else//!PACKING_ONE_SLICE_PER_LAYER | |
| 528 | + if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) { | |
| 529 | + WelsLog (*ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", | |
| 530 | + iCountNumLayers, MAX_LAYER_NUM_OF_FRAME); | |
| 531 | + return 1; | |
| 532 | + } | |
| 533 | +#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 534 | +#endif//!MT_ENABLED | |
| 535 | + | |
| 536 | + if (NULL != pCountLayers) | |
| 537 | + *pCountLayers = iCountNumLayers; | |
| 538 | + if (NULL != pCountNals) | |
| 539 | + *pCountNals = iCountNumNals; | |
| 540 | + return 0; | |
| 541 | +} | |
| 542 | + | |
| 543 | +/*! | |
| 544 | + * \brief alloc spatial layers pictures (I420 based source pictures) | |
| 545 | + */ | |
| 546 | +int32_t AllocSpatialPictures (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pParam) { | |
| 547 | + CMemoryAlign* pMa = (*ppCtx)->pMemAlign; | |
| 548 | + const int32_t kiDlayerCount = pParam->iNumDependencyLayer; | |
| 549 | + int32_t iDlayerIndex = 0; | |
| 550 | + | |
| 551 | + // spatial pictures | |
| 552 | + iDlayerIndex = 0; | |
| 553 | + do { | |
| 554 | + const int32_t kiPicWidth = pParam->sDependencyLayers[iDlayerIndex].iFrameWidth; | |
| 555 | + const int32_t kiPicHeight = pParam->sDependencyLayers[iDlayerIndex].iFrameHeight; | |
| 556 | + const uint8_t kuiLayerInTemporal = 2 + WELS_MAX (pParam->sDependencyLayers[iDlayerIndex].iHighestTemporalId, 1); | |
| 557 | + const uint8_t kuiRefNumInTemporal = kuiLayerInTemporal + pParam->iLTRRefNum; | |
| 558 | + uint8_t i = 0; | |
| 559 | + | |
| 560 | + do { | |
| 561 | + SPicture* pPic = AllocPicture (pMa, kiPicWidth, kiPicHeight, false); | |
| 562 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pPic), FreeMemorySvc (ppCtx); *ppCtx = NULL) | |
| 563 | + (*ppCtx)->pSpatialPic[iDlayerIndex][i] = pPic; | |
| 564 | + ++ i; | |
| 565 | + } while (i < kuiRefNumInTemporal); | |
| 566 | + | |
| 567 | + (*ppCtx)->uiSpatialLayersInTemporal[iDlayerIndex] = kuiLayerInTemporal; | |
| 568 | + (*ppCtx)->uiSpatialPicNum[iDlayerIndex] = kuiRefNumInTemporal; | |
| 569 | + ++ iDlayerIndex; | |
| 570 | + } while (iDlayerIndex < kiDlayerCount); | |
| 571 | + | |
| 572 | + return 0; | |
| 573 | +} | |
| 574 | + | |
| 575 | +void FreeSpatialPictures (sWelsEncCtx* pCtx) { | |
| 576 | + CMemoryAlign* pMa = pCtx->pMemAlign; | |
| 577 | + int32_t j = 0; | |
| 578 | + while (j < pCtx->pSvcParam->iNumDependencyLayer) { | |
| 579 | + uint8_t i = 0; | |
| 580 | + uint8_t uiRefNumInTemporal = pCtx->uiSpatialPicNum[j]; | |
| 581 | + | |
| 582 | + while (i < uiRefNumInTemporal) { | |
| 583 | + if (NULL != pCtx->pSpatialPic[j][i]) { | |
| 584 | + FreePicture (pMa, &pCtx->pSpatialPic[j][i]); | |
| 585 | + } | |
| 586 | + ++ i; | |
| 587 | + } | |
| 588 | + pCtx->uiSpatialLayersInTemporal[j] = 0; | |
| 589 | + ++ j; | |
| 590 | + } | |
| 591 | + | |
| 592 | +} | |
| 593 | + | |
| 594 | +static void InitMbInfo (sWelsEncCtx* pEnc, SMB* pList, SDqLayer* pLayer, const int32_t kiDlayerId, | |
| 595 | + const int32_t kiMaxMbNum) { | |
| 596 | + int32_t iMbWidth = pLayer->iMbWidth; | |
| 597 | + int32_t iMbHeight = pLayer->iMbHeight; | |
| 598 | + int32_t iIdx; | |
| 599 | + int32_t iMbNum = iMbWidth * iMbHeight; | |
| 600 | + SSliceCtx* pSliceCtx = pLayer->pSliceEncCtx; | |
| 601 | + uint32_t uiNeighborAvail; | |
| 602 | + const int32_t kiOffset = (kiDlayerId & 0x01) * kiMaxMbNum; | |
| 603 | + SMVUnitXY (*pLayerMvUnitBlock4x4)[MB_BLOCK4x4_NUM] = (SMVUnitXY (*)[MB_BLOCK4x4_NUM]) ( | |
| 604 | + &pEnc->pMvUnitBlock4x4[MB_BLOCK4x4_NUM * kiOffset]); | |
| 605 | + int8_t (*pLayerRefIndexBlock8x8)[MB_BLOCK8x8_NUM] = (int8_t (*)[MB_BLOCK8x8_NUM]) ( | |
| 606 | + &pEnc->pRefIndexBlock4x4[MB_BLOCK8x8_NUM * kiOffset]); | |
| 607 | + | |
| 608 | + for (iIdx = 0; iIdx < iMbNum; iIdx++) { | |
| 609 | + BOOL_T bLeft; | |
| 610 | + BOOL_T bTop; | |
| 611 | + BOOL_T bLeftTop; | |
| 612 | + BOOL_T bRightTop; | |
| 613 | + int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY; | |
| 614 | + uint8_t uiSliceIdc; | |
| 615 | + | |
| 616 | + pList[iIdx].iMbX = pEnc->pStrideTab->pMbIndexX[kiDlayerId][iIdx]; | |
| 617 | + pList[iIdx].iMbY = pEnc->pStrideTab->pMbIndexY[kiDlayerId][iIdx]; | |
| 618 | + pList[iIdx].iMbXY = iIdx; | |
| 619 | + | |
| 620 | + uiSliceIdc = WelsMbToSliceIdc (pSliceCtx, iIdx); | |
| 621 | + iLeftXY = iIdx - 1; | |
| 622 | + iTopXY = iIdx - iMbWidth; | |
| 623 | + iLeftTopXY = iTopXY - 1; | |
| 624 | + iRightTopXY = iTopXY + 1; | |
| 625 | + | |
| 626 | + bLeft = (pList[iIdx].iMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc (pSliceCtx, iLeftXY)); | |
| 627 | + bTop = (pList[iIdx].iMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pSliceCtx, iTopXY)); | |
| 628 | + bLeftTop = (pList[iIdx].iMbX > 0) && (pList[iIdx].iMbY > 0) && (uiSliceIdc == | |
| 629 | + WelsMbToSliceIdc (pSliceCtx, iLeftTopXY)); | |
| 630 | + bRightTop = (pList[iIdx].iMbX < (iMbWidth - 1)) && (pList[iIdx].iMbY > 0) && (uiSliceIdc == | |
| 631 | + WelsMbToSliceIdc (pSliceCtx, iRightTopXY)); | |
| 632 | + | |
| 633 | + uiNeighborAvail = 0; | |
| 634 | + if (bLeft) { | |
| 635 | + uiNeighborAvail |= LEFT_MB_POS; | |
| 636 | + } | |
| 637 | + if (bTop) { | |
| 638 | + uiNeighborAvail |= TOP_MB_POS; | |
| 639 | + } | |
| 640 | + if (bLeftTop) { | |
| 641 | + uiNeighborAvail |= TOPLEFT_MB_POS; | |
| 642 | + } | |
| 643 | + if (bRightTop) { | |
| 644 | + uiNeighborAvail |= TOPRIGHT_MB_POS; | |
| 645 | + } | |
| 646 | + pList[iIdx].uiSliceIdc = uiSliceIdc; // merge from svc_hd_opt_b for multiple slices coding | |
| 647 | + pList[iIdx].uiNeighborAvail = uiNeighborAvail; | |
| 648 | + uiNeighborAvail = 0; | |
| 649 | + if (pList[iIdx].iMbX >= BASE_MV_MB_NMB) | |
| 650 | + uiNeighborAvail |= LEFT_MB_POS; | |
| 651 | + if (pList[iIdx].iMbX <= (iMbWidth - 1 - BASE_MV_MB_NMB)) | |
| 652 | + uiNeighborAvail |= RIGHT_MB_POS; | |
| 653 | + if (pList[iIdx].iMbY >= BASE_MV_MB_NMB) | |
| 654 | + uiNeighborAvail |= TOP_MB_POS; | |
| 655 | + if (pList[iIdx].iMbY <= (iMbHeight - 1 - BASE_MV_MB_NMB)) | |
| 656 | + uiNeighborAvail |= BOTTOM_MB_POS; | |
| 657 | + | |
| 658 | + pList[iIdx].sMv = pLayerMvUnitBlock4x4[iIdx]; | |
| 659 | + pList[iIdx].pRefIndex = pLayerRefIndexBlock8x8[iIdx]; | |
| 660 | + pList[iIdx].pSadCost = &pEnc->pSadCostMb[iIdx]; | |
| 661 | + pList[iIdx].pIntra4x4PredMode = &pEnc->pIntra4x4PredModeBlocks[iIdx * INTRA_4x4_MODE_NUM]; | |
| 662 | + pList[iIdx].pNonZeroCount = &pEnc->pNonZeroCountBlocks[iIdx * MB_LUMA_CHROMA_BLOCK4x4_NUM]; | |
| 663 | + } | |
| 664 | +} | |
| 665 | + | |
| 666 | + | |
| 667 | +int32_t InitMbListD (sWelsEncCtx** ppCtx) { | |
| 668 | + int32_t iNumDlayer = (*ppCtx)->pSvcParam->iNumDependencyLayer; | |
| 669 | + int32_t iMbSize[MAX_DEPENDENCY_LAYER] = { 0 }; | |
| 670 | + int32_t iOverallMbNum = 0; | |
| 671 | + int32_t iMbWidth = 0; | |
| 672 | + int32_t iMbHeight = 0; | |
| 673 | + int32_t i; | |
| 674 | + | |
| 675 | + if (iNumDlayer > MAX_DEPENDENCY_LAYER) | |
| 676 | + return 1; | |
| 677 | + | |
| 678 | + for (i = 0; i < iNumDlayer; i++) { | |
| 679 | + iMbWidth = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameWidth + 15) >> 4; | |
| 680 | + iMbHeight = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameHeight + 15) >> 4; | |
| 681 | + iMbSize[i] = iMbWidth * iMbHeight; | |
| 682 | + iOverallMbNum += iMbSize[i]; | |
| 683 | + } | |
| 684 | + | |
| 685 | + (*ppCtx)->ppMbListD = static_cast<SMB**> ((*ppCtx)->pMemAlign->WelsMalloc (iNumDlayer * sizeof (SMB*), "ppMbListD")); | |
| 686 | + (*ppCtx)->ppMbListD[0] = NULL; | |
| 687 | + WELS_VERIFY_RETURN_PROC_IF (1, (*ppCtx)->ppMbListD == NULL, FreeMemorySvc (ppCtx)); | |
| 688 | + (*ppCtx)->ppMbListD[0] = static_cast<SMB*> ((*ppCtx)->pMemAlign->WelsMallocz (iOverallMbNum * sizeof (SMB), | |
| 689 | + "ppMbListD[0]")); | |
| 690 | + WELS_VERIFY_RETURN_PROC_IF (1, (*ppCtx)->ppMbListD[0] == NULL, FreeMemorySvc (ppCtx)); | |
| 691 | + (*ppCtx)->ppDqLayerList[0]->sMbDataP = (*ppCtx)->ppMbListD[0]; | |
| 692 | + InitMbInfo (*ppCtx, (*ppCtx)->ppMbListD[0], (*ppCtx)->ppDqLayerList[0], 0, iMbSize[iNumDlayer - 1]); | |
| 693 | + for (i = 1; i < iNumDlayer; i++) { | |
| 694 | + (*ppCtx)->ppMbListD[i] = (*ppCtx)->ppMbListD[i - 1] + iMbSize[i - 1]; | |
| 695 | + (*ppCtx)->ppDqLayerList[i]->sMbDataP = (*ppCtx)->ppMbListD[i]; | |
| 696 | + InitMbInfo (*ppCtx, (*ppCtx)->ppMbListD[i], (*ppCtx)->ppDqLayerList[i], i, iMbSize[iNumDlayer - 1]); | |
| 697 | + } | |
| 698 | + | |
| 699 | + return 0; | |
| 700 | +} | |
| 701 | + | |
| 702 | +int32_t AllocMbCacheAligned (SMbCache* pMbCache, CMemoryAlign* pMa) { | |
| 703 | + pMbCache->pCoeffLevel = (int16_t*)pMa->WelsMalloc (MB_COEFF_LIST_SIZE * sizeof (int16_t), "pMbCache->pCoeffLevel"); | |
| 704 | + WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pCoeffLevel)); | |
| 705 | + pMbCache->pMemPredMb = (uint8_t*)pMa->WelsMalloc (2 * 256 * sizeof (uint8_t), "pMbCache->pMemPredMb"); | |
| 706 | + WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pMemPredMb)); | |
| 707 | + pMbCache->pSkipMb = (uint8_t*)pMa->WelsMalloc (384 * sizeof (uint8_t), "pMbCache->pSkipMb"); | |
| 708 | + WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pSkipMb)); | |
| 709 | + pMbCache->pMemPredBlk4 = (uint8_t*)pMa->WelsMalloc (2 * 16 * sizeof (uint8_t), "pMbCache->pMemPredBlk4"); | |
| 710 | + WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pMemPredBlk4)); | |
| 711 | + pMbCache->pBufferInterPredMe = (uint8_t*)pMa->WelsMalloc (4 * 640 * sizeof (uint8_t), "pMbCache->pBufferInterPredMe"); | |
| 712 | + WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pBufferInterPredMe)); | |
| 713 | + pMbCache->pPrevIntra4x4PredModeFlag = (bool_t*)pMa->WelsMalloc (16 * sizeof (bool_t), | |
| 714 | + "pMbCache->pPrevIntra4x4PredModeFlag"); | |
| 715 | + WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pPrevIntra4x4PredModeFlag)); | |
| 716 | + pMbCache->pRemIntra4x4PredModeFlag = (int8_t*)pMa->WelsMalloc (16 * sizeof (int8_t), | |
| 717 | + "pMbCache->pRemIntra4x4PredModeFlag"); | |
| 718 | + WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pRemIntra4x4PredModeFlag)); | |
| 719 | + pMbCache->pDct = (SDCTCoeff*)pMa->WelsMalloc (sizeof (SDCTCoeff), "pMbCache->pDct"); | |
| 720 | + WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pDct)); | |
| 721 | + return 0; | |
| 722 | +} | |
| 723 | + | |
| 724 | +void FreeMbCache (SMbCache* pMbCache, CMemoryAlign* pMa) { | |
| 725 | + if (NULL != pMbCache->pCoeffLevel) { | |
| 726 | + pMa->WelsFree (pMbCache->pCoeffLevel, "pMbCache->pCoeffLevel"); | |
| 727 | + pMbCache->pCoeffLevel = NULL; | |
| 728 | + } | |
| 729 | + if (NULL != pMbCache->pMemPredMb) { | |
| 730 | + pMa->WelsFree (pMbCache->pMemPredMb, "pMbCache->pMemPredMb"); | |
| 731 | + pMbCache->pMemPredMb = NULL; | |
| 732 | + } | |
| 733 | + if (NULL != pMbCache->pSkipMb) { | |
| 734 | + pMa->WelsFree (pMbCache->pSkipMb, "pMbCache->pSkipMb"); | |
| 735 | + pMbCache->pSkipMb = NULL; | |
| 736 | + } | |
| 737 | + if (NULL != pMbCache->pMemPredBlk4) { | |
| 738 | + pMa->WelsFree (pMbCache->pMemPredBlk4, "pMbCache->pMemPredBlk4"); | |
| 739 | + pMbCache->pMemPredBlk4 = NULL; | |
| 740 | + } | |
| 741 | + if (NULL != pMbCache->pBufferInterPredMe) { | |
| 742 | + pMa->WelsFree (pMbCache->pBufferInterPredMe, "pMbCache->pBufferInterPredMe"); | |
| 743 | + pMbCache->pBufferInterPredMe = NULL; | |
| 744 | + } | |
| 745 | + if (NULL != pMbCache->pPrevIntra4x4PredModeFlag) { | |
| 746 | + pMa->WelsFree (pMbCache->pPrevIntra4x4PredModeFlag, "pMbCache->pPrevIntra4x4PredModeFlag"); | |
| 747 | + pMbCache->pPrevIntra4x4PredModeFlag = NULL; | |
| 748 | + } | |
| 749 | + if (NULL != pMbCache->pRemIntra4x4PredModeFlag) { | |
3283 more lines aren’t shown here.