Showing the changes to codec/encoder/core/src/encoder_ext.cpp (1 of 308 files). Show all
Unified · Split
| @@ -0,0 +1,4250 @@ | ||
| 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 | |