Showing the changes to codec/encoder/core/src/encoder_ext.cpp (1 of 225 files). Show all
Unified · Split
| @@ -1,4250 +1,4032 @@ | |||
| 1 | /*! | 1 | /*! |
| 2 | * \copy | 2 | * \copy |
| 3 | * Copyright (c) 2009-2013, Cisco Systems | 3 | * Copyright (c) 2009-2013, Cisco Systems |
| 4 | * All rights reserved. | 4 | * All rights reserved. |
| 5 | * | 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions |
| 8 | * are met: | 8 | * are met: |
| 9 | * | 9 | * |
| 10 | * * Redistributions of source code must retain the above copyright | 10 | * * Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * | 12 | * |
| 13 | * * Redistributions in binary form must reproduce the above copyright | 13 | * * Redistributions in binary form must reproduce the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer in | 14 | * notice, this list of conditions and the following disclaimer in |
| 15 | * the documentation and/or other materials provided with the | 15 | * the documentation and/or other materials provided with the |
| 16 | * distribution. | 16 | * distribution. |
| 17 | * | 17 | * |
| 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 21 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| 22 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | 22 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| 24 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 24 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | 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 | 28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. |
| 30 | * | 30 | * |
| 31 | * | 31 | * |
| 32 | * \file encoder_ext.c | 32 | * \file encoder_ext.c |
| 33 | * | 33 | * |
| 34 | * \brief core encoder for SVC | 34 | * \brief core encoder for SVC |
| 35 | * | 35 | * |
| 36 | * \date 7/24/2009 Created | 36 | * \date 7/24/2009 Created |
| 37 | * | 37 | * |
| 38 | ************************************************************************************* | 38 | ************************************************************************************* |
| 39 | */ | 39 | */ |
| 40 | #include <string.h> | 40 | #include <string.h> |
| 41 | #include <stdlib.h> | 41 | #include <stdlib.h> |
| 42 | #include <assert.h> | 42 | #include <assert.h> |
| 43 | 43 | ||
| 44 | #include "encoder.h" | 44 | #include "encoder.h" |
| 45 | #include "extern.h" | 45 | #include "extern.h" |
| 46 | #include "encoder_context.h" | 46 | #include "encoder_context.h" |
| 47 | #include "typedefs.h" | 47 | #include "typedefs.h" |
| 48 | #include "wels_const.h" | 48 | #include "wels_const.h" |
| 49 | #include "wels_common_basis.h" | 49 | #include "wels_common_basis.h" |
| 50 | #include "codec_def.h" | 50 | #include "codec_def.h" |
| 51 | #include "param_svc.h" | 51 | #include "param_svc.h" |
| 52 | #include "cpu_core.h" | 52 | #include "cpu_core.h" |
| 53 | #include "cpu.h" | 53 | #include "cpu.h" |
| 54 | #include "utils.h" | 54 | #include "utils.h" |
| 55 | #include "svc_enc_frame.h" | 55 | #include "svc_enc_frame.h" |
| 56 | #include "svc_enc_golomb.h" | 56 | #include "svc_enc_golomb.h" |
| 57 | #include "svc_enc_slice_segment.h" | 57 | #include "svc_enc_slice_segment.h" |
| 58 | #include "au_set.h" | 58 | #include "au_set.h" |
| 59 | #include "picture_handle.h" | 59 | #include "picture_handle.h" |
| 60 | #include "codec_app_def.h" | 60 | #include "codec_app_def.h" |
| 61 | #include "svc_base_layer_md.h" | 61 | #include "svc_base_layer_md.h" |
| 62 | #include "svc_encode_slice.h" | 62 | #include "svc_encode_slice.h" |
| 63 | #include "decode_mb_aux.h" | 63 | #include "decode_mb_aux.h" |
| 64 | #include "deblocking.h" | 64 | #include "deblocking.h" |
| 65 | #include "rc.h" | 65 | #include "rc.h" |
| 66 | #include "ref_list_mgr_svc.h" | 66 | #include "ref_list_mgr_svc.h" |
| 67 | #include "md.h" | 67 | #include "md.h" |
| 68 | #include "ls_defines.h" | 68 | #include "ls_defines.h" |
| 69 | #include "set_mb_syn_cavlc.h" | 69 | #include "set_mb_syn_cavlc.h" |
| 70 | #include "crt_util_safe_x.h" // Safe CRT routines like utils for cross platforms | 70 | #include "crt_util_safe_x.h" // Safe CRT routines like utils for cross platforms |
| 71 | #include "array_stack_align.h" | 71 | #include "array_stack_align.h" |
| 72 | // for MT, 4/22/2010 | 72 | // for MT, 4/22/2010 |
| 73 | #include "slice_multi_threading.h" | 73 | #include "slice_multi_threading.h" |
| 74 | #if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | 74 | #if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) |
| 75 | #include "measure_time.h" | 75 | #include "measure_time.h" |
| 76 | #endif//DYNAMIC_SLICE_ASSIGN | 76 | #endif//DYNAMIC_SLICE_ASSIGN |
| 77 | 77 | ||
| 78 | namespace WelsSVCEnc { | 78 | namespace WelsSVCEnc { |
| 79 | 79 | ||
| 80 | 80 | ||
| 81 | int32_t WelsCodeOnePicPartition( sWelsEncCtx *pCtx, | 81 | int32_t WelsCodeOnePicPartition (sWelsEncCtx* pCtx, |
| 82 | SLayerBSInfo *pLbi, | 82 | SLayerBSInfo* pLbi, |
| 83 | int32_t *pNalIdxInLayer, | 83 | int32_t* pNalIdxInLayer, |
| 84 | int32_t* pLayerSize, | 84 | int32_t* pLayerSize, |
| 85 | int32_t iFirstMbInPartition, // first mb inclusive in partition | 85 | int32_t iFirstMbInPartition, // first mb inclusive in partition |
| 86 | int32_t iEndMbInPartition, // end mb exclusive in partition | 86 | int32_t iEndMbInPartition, // end mb exclusive in partition |
| 87 | int32_t iStartSliceIdx | 87 | int32_t iStartSliceIdx |
| 88 | ); | 88 | ); |
| 89 | 89 | ||
| 90 | 90 | ||
| 91 | /*! | 91 | /*! |
| 92 | * \brief validate checking in parameter configuration | 92 | * \brief validate checking in parameter configuration |
| 93 | * \pParam pParam SWelsSvcCodingParam* | 93 | * \pParam pParam SWelsSvcCodingParam* |
| 94 | * \return successful - 0; otherwise none 0 for failed | 94 | * \return successful - 0; otherwise none 0 for failed |
| 95 | */ | 95 | */ |
| 96 | int32_t ParamValidation( SWelsSvcCodingParam *pCfg ) | 96 | int32_t ParamValidation (SWelsSvcCodingParam* pCfg) { |
| 97 | { | 97 | float fMaxFrameRate = 0.0f; |
| 98 | float fMaxFrameRate = 0.0f; | 98 | const float fEpsn = 0.000001f; |
| 99 | const float fEpsn = 0.000001f; | 99 | int32_t i = 0; |
| 100 | int32_t i = 0; | 100 | int32_t iLastSpatialWidth = 0; |
| 101 | int32_t iLastSpatialWidth = 0; | 101 | int32_t iLastSpatialHeight = 0; |
| 102 | int32_t iLastSpatialHeight = 0; | 102 | float fLastFrameRateIn = 0.0f; |
| 103 | float fLastFrameRateIn = 0.0f; | 103 | float fLastFrameRateOut = 0.0f; |
| 104 | float fLastFrameRateOut = 0.0f; | 104 | SDLayerParam* pLastSpatialParam = NULL; |
| 105 | SDLayerParam *pLastSpatialParam = NULL; | 105 | |
| 106 | 106 | assert (pCfg != NULL); | |
| 107 | assert( pCfg != NULL ); | 107 | |
| 108 | 108 | for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) { | |
| 109 | for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) | 109 | SDLayerParam* fDlp = &pCfg->sDependencyLayers[i]; |
| 110 | { | 110 | if (fDlp->fOutputFrameRate > fDlp->fInputFrameRate || (fDlp->fInputFrameRate >= -fEpsn |
| 111 | SDLayerParam *fDlp = &pCfg->sDependencyLayers[i]; | 111 | && fDlp->fInputFrameRate <= fEpsn) |
| 112 | if ( fDlp->fOutputFrameRate > fDlp->fInputFrameRate || (fDlp->fInputFrameRate >= -fEpsn && fDlp->fInputFrameRate <= fEpsn) | 112 | || (fDlp->fOutputFrameRate >= -fEpsn && fDlp->fOutputFrameRate <= fEpsn)) { |
| 113 | || (fDlp->fOutputFrameRate >= -fEpsn && fDlp->fOutputFrameRate <= fEpsn) ) | 113 | #if defined (_DEBUG) |
| 114 | { | 114 | fprintf (stderr, "Invalid settings in input frame rate(%.6f) or output frame rate(%.6f) of layer #%d config file..\n", |
| 115 | #if defined (_DEBUG) | 115 | fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i); |
| 116 | fprintf(stderr, "Invalid settings in input frame rate(%.6f) or output frame rate(%.6f) of layer #%d config file..\n", | 116 | #endif |
| 117 | fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i); | 117 | return 1; |
| 118 | #endif | 118 | } |
| 119 | return 1; | 119 | if (UINT_MAX == GetLogFactor (fDlp->fOutputFrameRate, fDlp->fInputFrameRate)) { |
| 120 | } | 120 | #if defined (_DEBUG) |
| 121 | if ( UINT_MAX == GetLogFactor(fDlp->fOutputFrameRate, fDlp->fInputFrameRate) ) | 121 | fprintf (stderr, |
| 122 | { | 122 | "Invalid settings in input frame rate(%.6f) and output frame rate(%.6f) of layer #%d config file: iResult of output frame rate divided by input frame rate should be power of 2(i.e,in/pOut=2^n)..\n", |
| 123 | #if defined (_DEBUG) | 123 | fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i); |
| 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", | 124 | #endif |
| 125 | fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i); | 125 | return 1; |
| 126 | #endif | 126 | } |
| 127 | return 1; | 127 | } |
| 128 | } | 128 | |
| 129 | } | 129 | for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) { |
| 130 | 130 | SDLayerParam* fDlp = &pCfg->sDependencyLayers[i]; | |
| 131 | for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) | 131 | if (fDlp->fInputFrameRate > fMaxFrameRate) |
| 132 | { | 132 | fMaxFrameRate = fDlp->fInputFrameRate; |
| 133 | SDLayerParam *fDlp = &pCfg->sDependencyLayers[i]; | 133 | } |
| 134 | if ( fDlp->fInputFrameRate > fMaxFrameRate ) | 134 | |
| 135 | fMaxFrameRate = fDlp->fInputFrameRate; | 135 | if (fMaxFrameRate > fEpsn && (fMaxFrameRate - pCfg->fMaxFrameRate > fEpsn |
| 136 | } | 136 | || fMaxFrameRate - pCfg->fMaxFrameRate < -fEpsn)) { |
| 137 | 137 | pCfg->fMaxFrameRate = fMaxFrameRate; | |
| 138 | if ( fMaxFrameRate > fEpsn && (fMaxFrameRate - pCfg->fMaxFrameRate > fEpsn || fMaxFrameRate - pCfg->fMaxFrameRate < -fEpsn) ) | 138 | } |
| 139 | { | 139 | |
| 140 | pCfg->fMaxFrameRate = fMaxFrameRate; | 140 | for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) { |
| 141 | } | 141 | SDLayerParam* fDlp = &pCfg->sDependencyLayers[i]; |
| 142 | 142 | ||
| 143 | for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) | 143 | pLastSpatialParam = fDlp; |
| 144 | { | 144 | iLastSpatialWidth = fDlp->iFrameWidth; |
| 145 | SDLayerParam *fDlp = &pCfg->sDependencyLayers[i]; | 145 | iLastSpatialHeight = fDlp->iFrameHeight; |
| 146 | 146 | fLastFrameRateIn = fDlp->fInputFrameRate; | |
| 147 | pLastSpatialParam = fDlp; | 147 | fLastFrameRateOut = fDlp->fOutputFrameRate; |
| 148 | iLastSpatialWidth = fDlp->iFrameWidth; | 148 | } |
| 149 | iLastSpatialHeight = fDlp->iFrameHeight; | 149 | |
| 150 | fLastFrameRateIn = fDlp->fInputFrameRate; | 150 | return 0; |
| 151 | fLastFrameRateOut = fDlp->fOutputFrameRate; | 151 | } |
| 152 | } | 152 | |
| 153 | 153 | int32_t ParamValidationExt (void* pParam) { | |
| 154 | return 0; | 154 | SWelsSvcCodingParam* pCodingParam = (SWelsSvcCodingParam*)pParam; |
| 155 | } | 155 | int8_t i = 0; |
| 156 | 156 | int32_t iIdx = 0; | |
| 157 | int32_t ParamValidationExt( void *pParam ) | 157 | |
| 158 | { | 158 | assert (pCodingParam != NULL); |
| 159 | SWelsSvcCodingParam *pCodingParam = (SWelsSvcCodingParam *)pParam; | 159 | if (NULL == pCodingParam) |
| 160 | int8_t i = 0; | 160 | return 1; |
| 161 | int32_t iIdx = 0; | 161 | |
| 162 | 162 | if (pCodingParam->iNumDependencyLayer < 1 || pCodingParam->iNumDependencyLayer > MAX_DEPENDENCY_LAYER) { | |
| 163 | assert ( pCodingParam != NULL ); | 163 | #if defined (_DEBUG) |
| 164 | if ( NULL == pCodingParam ) | 164 | fprintf (stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumDependencyLayer: %d!\n", |
| 165 | return 1; | 165 | pCodingParam->iNumDependencyLayer); |
| 166 | 166 | #endif//#if _DEBUG | |
| 167 | if ( pCodingParam->iNumDependencyLayer < 1 || pCodingParam->iNumDependencyLayer > MAX_DEPENDENCY_LAYER ){ | 167 | |
| 168 | #if defined (_DEBUG) | 168 | return 1; |
| 169 | fprintf(stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumDependencyLayer: %d!\n", pCodingParam->iNumDependencyLayer); | 169 | } |
| 170 | #endif//#if _DEBUG | 170 | |
| 171 | 171 | if (pCodingParam->iNumTemporalLayer < 1 || pCodingParam->iNumTemporalLayer > MAX_TEMPORAL_LEVEL) { | |
| 172 | return 1; | 172 | #if defined (_DEBUG) |
| 173 | } | 173 | fprintf (stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumTemporalLayer: %d!\n", |
| 174 | 174 | pCodingParam->iNumTemporalLayer); | |
| 175 | if ( pCodingParam->iNumTemporalLayer < 1 || pCodingParam->iNumTemporalLayer > MAX_TEMPORAL_LEVEL ){ | 175 | #endif//#if _DEBUG |
| 176 | #if defined (_DEBUG) | 176 | return 1; |
| 177 | fprintf(stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumTemporalLayer: %d!\n", pCodingParam->iNumTemporalLayer); | 177 | } |
| 178 | #endif//#if _DEBUG | 178 | |
| 179 | return 1; | 179 | if (pCodingParam->uiGopSize < 1 || pCodingParam->uiGopSize > MAX_GOP_SIZE) { |
| 180 | } | 180 | #if defined (_DEBUG) |
| 181 | 181 | fprintf (stderr, "ParamValidationExt(), monitor invalid pCodingParam->uiGopSize: %d!\n", pCodingParam->uiGopSize); | |
| 182 | if ( pCodingParam->uiGopSize < 1 || pCodingParam->uiGopSize > MAX_GOP_SIZE ){ | 182 | #endif//#if _DEBUG |
| 183 | #if defined (_DEBUG) | 183 | return 1; |
| 184 | fprintf(stderr, "ParamValidationExt(), monitor invalid pCodingParam->uiGopSize: %d!\n", pCodingParam->uiGopSize); | 184 | } |
| 185 | #endif//#if _DEBUG | 185 | |
| 186 | return 1; | 186 | |
| 187 | } | 187 | if (pCodingParam->uiIntraPeriod && pCodingParam->uiIntraPeriod < pCodingParam->uiGopSize) { |
| 188 | 188 | #if defined (_DEBUG) | |
| 189 | 189 | fprintf (stderr, | |
| 190 | if ( pCodingParam->uiIntraPeriod && pCodingParam->uiIntraPeriod < pCodingParam->uiGopSize ) | 190 | "ParamValidationExt(), uiIntraPeriod(%d) should be not less than that of uiGopSize(%d) or -1 specified!\n", |
| 191 | { | 191 | pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize); |
| 192 | #if defined (_DEBUG) | 192 | #endif//#if _DEBUG |
| 193 | fprintf(stderr, "ParamValidationExt(), uiIntraPeriod(%d) should be not less than that of uiGopSize(%d) or -1 specified!\n", | 193 | return 1; |
| 194 | pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize); | 194 | } |
| 195 | #endif//#if _DEBUG | 195 | |
| 196 | return 1; | 196 | if (pCodingParam->uiIntraPeriod && (pCodingParam->uiIntraPeriod & (pCodingParam->uiGopSize - 1)) != 0) { |
| 197 | } | 197 | #if defined (_DEBUG) |
| 198 | 198 | fprintf (stderr, "ParamValidationExt(), uiIntraPeriod(%d) should be multiple of uiGopSize(%d) or -1 specified!\n", | |
| 199 | if ( pCodingParam->uiIntraPeriod && (pCodingParam->uiIntraPeriod & (pCodingParam->uiGopSize-1)) != 0 ) | 199 | pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize); |
| 200 | { | 200 | #endif//#if _DEBUG |
| 201 | #if defined (_DEBUG) | 201 | return 1; |
| 202 | fprintf(stderr, "ParamValidationExt(), uiIntraPeriod(%d) should be multiple of uiGopSize(%d) or -1 specified!\n", | 202 | } |
| 203 | pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize); | 203 | |
| 204 | #endif//#if _DEBUG | 204 | |
| 205 | return 1; | 205 | #ifdef MT_ENABLED |
| 206 | } | 206 | //about iMultipleThreadIdc, bDeblockingParallelFlag, iLoopFilterDisableIdc, & uiSliceMode |
| 207 | 207 | // (1) Single Thread | |
| 208 | 208 | // if (THREAD==1)//single thread | |
| 209 | #ifdef MT_ENABLED | 209 | // no parallel_deblocking: bDeblockingParallelFlag = 0; |
| 210 | //about iMultipleThreadIdc, bDeblockingParallelFlag, iLoopFilterDisableIdc, & uiSliceMode | 210 | // (2) Multi Thread: see uiSliceMode decision |
| 211 | // (1) Single Thread | 211 | if (pCodingParam->iMultipleThreadIdc == 1) { |
| 212 | // if (THREAD==1)//single thread | 212 | //now is single thread. no parallel deblocking, set flag=0 |
| 213 | // no parallel_deblocking: bDeblockingParallelFlag = 0; | 213 | pCodingParam->bDeblockingParallelFlag = false; |
| 214 | // (2) Multi Thread: see uiSliceMode decision | 214 | } else { |
| 215 | if ( pCodingParam->iMultipleThreadIdc == 1 ) | 215 | pCodingParam->bDeblockingParallelFlag = true; |
| 216 | { | 216 | } |
| 217 | //now is single thread. no parallel deblocking, set flag=0 | 217 | #else |
| 218 | pCodingParam->bDeblockingParallelFlag = false; | 218 | pCodingParam->bDeblockingParallelFlag = false; |
| 219 | } | 219 | #endif//MT_ENABLED |
| 220 | else | 220 | |
| 221 | { | 221 | for (i = 0; i < pCodingParam->iNumDependencyLayer; ++ i) { |
| 222 | pCodingParam->bDeblockingParallelFlag = true; | 222 | SDLayerParam* fDlp = &pCodingParam->sDependencyLayers[i]; |
| 223 | } | 223 | const int32_t kiPicWidth = fDlp->iFrameWidth; |
| 224 | #else | 224 | const int32_t kiPicHeight = fDlp->iFrameHeight; |
| 225 | pCodingParam->bDeblockingParallelFlag = false; | 225 | int32_t iMbWidth = 0; |
| 226 | #endif//MT_ENABLED | 226 | int32_t iMbHeight = 0; |
| 227 | 227 | int32_t iMbNumInFrame = 0; | |
| 228 | for ( i = 0; i < pCodingParam->iNumDependencyLayer; ++ i ){ | 228 | int32_t iMaxSliceNum = MAX_SLICES_NUM; |
| 229 | SDLayerParam *fDlp = &pCodingParam->sDependencyLayers[i]; | 229 | if (kiPicWidth <= 0 || kiPicHeight <= 0) { |
| 230 | const int32_t kiPicWidth = fDlp->iFrameWidth; | 230 | #if defined (_DEBUG) |
| 231 | const int32_t kiPicHeight= fDlp->iFrameHeight; | 231 | fprintf (stderr, "ParamValidationExt(), invalid %d x %d in dependency layer settings!\n", kiPicWidth, kiPicHeight); |
| 232 | int32_t iMbWidth = 0; | 232 | #endif//#if _DEBUG |
| 233 | int32_t iMbHeight = 0; | 233 | return 1; |
| 234 | int32_t iMbNumInFrame = 0; | 234 | } |
| 235 | int32_t iMaxSliceNum = MAX_SLICES_NUM; | 235 | if ((kiPicWidth & 0x0F) != 0 || (kiPicHeight & 0x0F) != 0) { |
| 236 | if ( kiPicWidth <= 0 || kiPicHeight <= 0 ){ | 236 | #if defined (_DEBUG) |
| 237 | #if defined (_DEBUG) | 237 | fprintf (stderr, |
| 238 | fprintf(stderr, "ParamValidationExt(), invalid %d x %d in dependency layer settings!\n", kiPicWidth, kiPicHeight); | 238 | "ParamValidationExt(), in layer #%d iWidth x iHeight(%d x %d) both should be multiple of 16, can not support with arbitrary size currently!\n", |
| 239 | #endif//#if _DEBUG | 239 | i, kiPicWidth, kiPicHeight); |
| 240 | return 1; | 240 | #endif//#if _DEBUG |
| 241 | } | 241 | return 1; |
| 242 | if ( (kiPicWidth & 0x0F) != 0 || (kiPicHeight & 0x0F) != 0 ){ | 242 | } |
| 243 | #if defined (_DEBUG) | 243 | |
| 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); | 244 | if (fDlp->sMso.uiSliceMode >= SM_RESERVED) { |
| 245 | #endif//#if _DEBUG | 245 | #if defined (_DEBUG) |
| 246 | return 1; | 246 | fprintf (stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", fDlp->sMso.uiSliceMode); |
| 247 | } | 247 | #endif//#if _DEBUG |
| 248 | 248 | return 1; | |
| 249 | if ( fDlp->sMso.uiSliceMode >= SM_RESERVED ){ | 249 | } |
| 250 | #if defined (_DEBUG) | 250 | |
| 251 | fprintf(stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", fDlp->sMso.uiSliceMode ); | 251 | //check pSlice settings under multi-pSlice |
| 252 | #endif//#if _DEBUG | 252 | if (kiPicWidth <= 16 && kiPicHeight <= 16) { |
| 253 | return 1; | 253 | //only have one MB, set to single_slice |
| 254 | } | 254 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; |
| 255 | 255 | } | |
| 256 | //check pSlice settings under multi-pSlice | 256 | switch (fDlp->sMso.uiSliceMode) { |
| 257 | if ( kiPicWidth<=16 && kiPicHeight<=16 ){ | 257 | case SM_SINGLE_SLICE: |
| 258 | //only have one MB, set to single_slice | 258 | fDlp->sMso.sSliceArgument.iSliceNum = 1; |
| 259 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | 259 | fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; |
| 260 | } | 260 | fDlp->sMso.sSliceArgument.iSliceNum = 0; |
| 261 | switch ( fDlp->sMso.uiSliceMode ) | 261 | for (iIdx = 0; iIdx < MAX_SLICES_NUM; iIdx++) { |
| 262 | { | 262 | fDlp->sMso.sSliceArgument.uiSliceMbNum[iIdx] = 0; |
| 263 | case SM_SINGLE_SLICE: | 263 | } |
| 264 | fDlp->sMso.sSliceArgument.iSliceNum = 1; | 264 | break; |
| 265 | fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | 265 | case SM_FIXEDSLCNUM_SLICE: { |
| 266 | fDlp->sMso.sSliceArgument.iSliceNum = 0; | 266 | fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; |
| 267 | for (iIdx=0; iIdx<MAX_SLICES_NUM;iIdx++) | 267 | |
| 268 | { | 268 | iMbWidth = (kiPicWidth + 15) >> 4; |
| 269 | fDlp->sMso.sSliceArgument.uiSliceMbNum[iIdx] = 0; | 269 | iMbHeight = (kiPicHeight + 15) >> 4; |
| 270 | } | 270 | iMbNumInFrame = iMbWidth * iMbHeight; |
| 271 | break; | 271 | iMaxSliceNum = MAX_SLICES_NUM; |
| 272 | case SM_FIXEDSLCNUM_SLICE: | 272 | if (fDlp->sMso.sSliceArgument.iSliceNum <= 0 |
| 273 | { | 273 | || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum) { |
| 274 | fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | 274 | #if defined (_DEBUG) |
| 275 | 275 | fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum); | |
| 276 | iMbWidth = (kiPicWidth+15)>>4; | 276 | #endif//#if _DEBUG |
| 277 | iMbHeight = (kiPicHeight+15)>>4; | 277 | return 1; |
| 278 | iMbNumInFrame = iMbWidth * iMbHeight; | 278 | } |
| 279 | iMaxSliceNum = MAX_SLICES_NUM; | 279 | if (fDlp->sMso.sSliceArgument.iSliceNum == 1) { |
| 280 | if ( fDlp->sMso.sSliceArgument.iSliceNum <= 0 | 280 | #if defined (_DEBUG) |
| 281 | || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum ) | 281 | fprintf (stderr, |
| 282 | { | 282 | "ParamValidationExt(), uiSliceNum(%d) you set for SM_FIXEDSLCNUM_SLICE, now turn to SM_SINGLE_SLICE type!\n", |
| 283 | #if defined (_DEBUG) | 283 | fDlp->sMso.sSliceArgument.iSliceNum); |
| 284 | fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum ); | 284 | #endif//#if _DEBUG |
| 285 | #endif//#if _DEBUG | 285 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; |
| 286 | return 1; | 286 | break; |
| 287 | } | 287 | } |
| 288 | if (fDlp->sMso.sSliceArgument.iSliceNum == 1) | 288 | if (pCodingParam->bEnableRc) { // multiple slices verify with gom |
| 289 | { | 289 | //check uiSliceNum |
| 290 | #if defined (_DEBUG) | 290 | GomValidCheckSliceNum (iMbWidth, iMbHeight, (int32_t*)&fDlp->sMso.sSliceArgument.iSliceNum); |
| 291 | fprintf(stderr, "ParamValidationExt(), uiSliceNum(%d) you set for SM_FIXEDSLCNUM_SLICE, now turn to SM_SINGLE_SLICE type!\n", fDlp->sMso.sSliceArgument.iSliceNum ); | 291 | assert (fDlp->sMso.sSliceArgument.iSliceNum > 1); |
| 292 | #endif//#if _DEBUG | 292 | //set uiSliceMbNum with current uiSliceNum |
| 293 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | 293 | GomValidCheckSliceMbNum (iMbWidth, iMbHeight, &fDlp->sMso.sSliceArgument); |
| 294 | break; | 294 | } else if (!CheckFixedSliceNumMultiSliceSetting (iMbNumInFrame, |
| 295 | } | 295 | &fDlp->sMso.sSliceArgument)) { // verify interleave mode settings |
| 296 | if (pCodingParam->bEnableRc) // multiple slices verify with gom | 296 | //check uiSliceMbNum with current uiSliceNum |
| 297 | { | 297 | #if defined (_DEBUG) |
| 298 | //check uiSliceNum | 298 | fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", |
| 299 | GomValidCheckSliceNum( iMbWidth, iMbHeight, (int32_t*)&fDlp->sMso.sSliceArgument.iSliceNum ); | 299 | fDlp->sMso.sSliceArgument.uiSliceMbNum[0]); |
| 300 | assert(fDlp->sMso.sSliceArgument.iSliceNum > 1); | 300 | #endif//#if _DEBUG |
| 301 | //set uiSliceMbNum with current uiSliceNum | 301 | return 1; |
| 302 | GomValidCheckSliceMbNum( iMbWidth, iMbHeight, &fDlp->sMso.sSliceArgument ); | 302 | } |
| 303 | } | 303 | // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting |
| 304 | else if ( !CheckFixedSliceNumMultiSliceSetting( iMbNumInFrame, &fDlp->sMso.sSliceArgument ) ) // verify interleave mode settings | 304 | if (iMbNumInFrame <= MIN_NUM_MB_PER_SLICE) { |
| 305 | {//check uiSliceMbNum with current uiSliceNum | 305 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; |
| 306 | #if defined (_DEBUG) | 306 | fDlp->sMso.sSliceArgument.iSliceNum = 1; |
| 307 | fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] ); | 307 | break; |
| 308 | #endif//#if _DEBUG | 308 | } |
| 309 | return 1; | 309 | } |
| 310 | } | 310 | break; |
| 311 | // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting | 311 | case SM_RASTER_SLICE: { |
| 312 | if ( iMbNumInFrame <= MIN_NUM_MB_PER_SLICE ) | 312 | fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; |
| 313 | { | 313 | |
| 314 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | 314 | iMbWidth = (kiPicWidth + 15) >> 4; |
| 315 | fDlp->sMso.sSliceArgument.iSliceNum = 1; | 315 | iMbHeight = (kiPicHeight + 15) >> 4; |
| 316 | break; | 316 | iMbNumInFrame = iMbWidth * iMbHeight; |
| 317 | } | 317 | iMaxSliceNum = MAX_SLICES_NUM; |
| 318 | } | 318 | if (fDlp->sMso.sSliceArgument.uiSliceMbNum[0] <= 0) { |
| 319 | break; | 319 | #if defined (_DEBUG) |
| 320 | case SM_RASTER_SLICE: | 320 | fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", |
| 321 | { | 321 | fDlp->sMso.sSliceArgument.uiSliceMbNum[0]); |
| 322 | fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | 322 | #endif//#if _DEBUG |
| 323 | 323 | return 1; | |
| 324 | iMbWidth = (kiPicWidth+15)>>4; | 324 | } |
| 325 | iMbHeight = (kiPicHeight+15)>>4; | 325 | |
| 326 | iMbNumInFrame = iMbWidth * iMbHeight; | 326 | if (!CheckRasterMultiSliceSetting (iMbNumInFrame, &fDlp->sMso.sSliceArgument)) { // verify interleave mode settings |
| 327 | iMaxSliceNum = MAX_SLICES_NUM; | 327 | #if defined (_DEBUG) |
| 328 | if ( fDlp->sMso.sSliceArgument.uiSliceMbNum[0] <= 0 ) | 328 | fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", |
| 329 | { | 329 | fDlp->sMso.sSliceArgument.uiSliceMbNum[0]); |
| 330 | #if defined (_DEBUG) | 330 | #endif//#if _DEBUG |
| 331 | fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] ); | 331 | return 1; |
| 332 | #endif//#if _DEBUG | 332 | } |
| 333 | return 1; | 333 | if (fDlp->sMso.sSliceArgument.iSliceNum <= 0 |
| 334 | } | 334 | || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum) { // verify interleave mode settings |
| 335 | 335 | #if defined (_DEBUG) | |
| 336 | if ( !CheckRasterMultiSliceSetting( iMbNumInFrame, &fDlp->sMso.sSliceArgument ) ) // verify interleave mode settings | 336 | fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) in SM_RASTER_SLICE settings!\n", |
| 337 | { | 337 | fDlp->sMso.sSliceArgument.iSliceNum); |
| 338 | #if defined (_DEBUG) | 338 | #endif//#if _DEBUG |
| 339 | fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] ); | 339 | return 1; |
| 340 | #endif//#if _DEBUG | 340 | } |
| 341 | return 1; | 341 | if (fDlp->sMso.sSliceArgument.iSliceNum == 1) { |
| 342 | } | 342 | #if defined (_DEBUG) |
| 343 | if ( fDlp->sMso.sSliceArgument.iSliceNum <= 0 || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum ) // verify interleave mode settings | 343 | fprintf (stderr, "ParamValidationExt(), pSlice setting for SM_RASTER_SLICE now turn to SM_SINGLE_SLICE!\n"); |
| 344 | { | 344 | #endif//#if _DEBUG |
| 345 | #if defined (_DEBUG) | 345 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; |
| 346 | fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) in SM_RASTER_SLICE settings!\n", fDlp->sMso.sSliceArgument.iSliceNum ); | 346 | break; |
| 347 | #endif//#if _DEBUG | 347 | } |
| 348 | return 1; | 348 | #ifdef MT_ENABLED |
| 349 | } | 349 | if (pCodingParam->bEnableRc && fDlp->sMso.sSliceArgument.iSliceNum > 1) { |
| 350 | if (fDlp->sMso.sSliceArgument.iSliceNum == 1) | 350 | #if defined (_DEBUG) |
| 351 | { | 351 | fprintf (stderr, "ParamValidationExt(), WARNING: GOM based RC do not support SM_RASTER_SLICE!\n"); |
| 352 | #if defined (_DEBUG) | 352 | #endif//#if _DEBUG |
| 353 | fprintf(stderr, "ParamValidationExt(), pSlice setting for SM_RASTER_SLICE now turn to SM_SINGLE_SLICE!\n" ); | 353 | } |
| 354 | #endif//#if _DEBUG | 354 | #endif |
| 355 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | 355 | // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting |
| 356 | break; | 356 | if (iMbNumInFrame <= MIN_NUM_MB_PER_SLICE) { |
| 357 | } | 357 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; |
| 358 | #ifdef MT_ENABLED | 358 | fDlp->sMso.sSliceArgument.iSliceNum = 1; |
| 359 | if (pCodingParam->bEnableRc && fDlp->sMso.sSliceArgument.iSliceNum > 1) | 359 | break; |
| 360 | { | 360 | } |
| 361 | #if defined (_DEBUG) | 361 | } |
| 362 | fprintf(stderr, "ParamValidationExt(), WARNING: GOM based RC do not support SM_RASTER_SLICE!\n" ); | 362 | break; |
| 363 | #endif//#if _DEBUG | 363 | case SM_ROWMB_SLICE: { |
| 364 | } | 364 | fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; |
| 365 | #endif | 365 | |
| 366 | // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting | 366 | iMbWidth = (kiPicWidth + 15) >> 4; |
| 367 | if ( iMbNumInFrame <= MIN_NUM_MB_PER_SLICE ) | 367 | iMbHeight = (kiPicHeight + 15) >> 4; |
| 368 | { | 368 | iMaxSliceNum = MAX_SLICES_NUM; |
| 369 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | 369 | if (iMbHeight > iMaxSliceNum) { |
| 370 | fDlp->sMso.sSliceArgument.iSliceNum = 1; | 370 | #if defined (_DEBUG) |
| 371 | break; | 371 | fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings more than MAX!\n", iMbHeight); |
| 372 | } | 372 | #endif//#if _DEBUG |
| 373 | } | 373 | return 1; |
| 374 | break; | 374 | } |
| 375 | case SM_ROWMB_SLICE: | 375 | fDlp->sMso.sSliceArgument.iSliceNum = iMbHeight; |
| 376 | { | 376 | |
| 377 | fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0; | 377 | if (fDlp->sMso.sSliceArgument.iSliceNum <= 0) { |
| 378 | 378 | #if defined (_DEBUG) | |
| 379 | iMbWidth = (kiPicWidth+15)>>4; | 379 | fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum); |
| 380 | iMbHeight = (kiPicHeight+15)>>4; | 380 | #endif//#if _DEBUG |
| 381 | iMaxSliceNum = MAX_SLICES_NUM; | 381 | return 1; |
| 382 | if ( iMbHeight > iMaxSliceNum ) | 382 | } |
| 383 | { | 383 | if (!CheckRowMbMultiSliceSetting (iMbWidth, &fDlp->sMso.sSliceArgument)) { // verify interleave mode settings |
| 384 | #if defined (_DEBUG) | 384 | #if defined (_DEBUG) |
| 385 | fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings more than MAX!\n", iMbHeight ); | 385 | fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", |
| 386 | #endif//#if _DEBUG | 386 | fDlp->sMso.sSliceArgument.uiSliceMbNum[0]); |
| 387 | return 1; | 387 | #endif//#if _DEBUG |
| 388 | } | 388 | return 1; |
| 389 | fDlp->sMso.sSliceArgument.iSliceNum = iMbHeight; | 389 | } |
| 390 | 390 | } | |
| 391 | if ( fDlp->sMso.sSliceArgument.iSliceNum <= 0 ) | 391 | break; |
| 392 | { | 392 | case SM_DYN_SLICE: { |
| 393 | #if defined (_DEBUG) | 393 | iMbWidth = (kiPicWidth + 15) >> 4; |
| 394 | fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum ); | 394 | iMbHeight = (kiPicHeight + 15) >> 4; |
| 395 | #endif//#if _DEBUG | 395 | if (fDlp->sMso.sSliceArgument.uiSliceSizeConstraint <= 0) { |
| 396 | return 1; | 396 | #if defined (_DEBUG) |
| 397 | } | 397 | fprintf (stderr, "ParamValidationExt(), invalid iSliceSize (%d) settings!\n", |
| 398 | if ( !CheckRowMbMultiSliceSetting( iMbWidth, &fDlp->sMso.sSliceArgument ) ) // verify interleave mode settings | 398 | fDlp->sMso.sSliceArgument.uiSliceSizeConstraint); |
| 399 | { | 399 | #endif//#if _DEBUG |
| 400 | #if defined (_DEBUG) | 400 | return 1; |
| 401 | fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] ); | 401 | } |
| 402 | #endif//#if _DEBUG | 402 | // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting |
| 403 | return 1; | 403 | if (iMbWidth * iMbHeight <= MIN_NUM_MB_PER_SLICE) { |
| 404 | } | 404 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; |
| 405 | } | 405 | fDlp->sMso.sSliceArgument.iSliceNum = 1; |
| 406 | break; | 406 | break; |
| 407 | case SM_DYN_SLICE: | 407 | } |
| 408 | { | 408 | } |
| 409 | iMbWidth = (kiPicWidth+15)>>4; | 409 | break; |
| 410 | iMbHeight = (kiPicHeight+15)>>4; | 410 | default: { |
| 411 | if ( fDlp->sMso.sSliceArgument.uiSliceSizeConstraint <= 0 ) | 411 | |
| 412 | { | 412 | #if defined (_DEBUG) |
| 413 | #if defined (_DEBUG) | 413 | fprintf (stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", |
| 414 | fprintf(stderr, "ParamValidationExt(), invalid iSliceSize (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceSizeConstraint ); | 414 | pCodingParam->sDependencyLayers[0].sMso.uiSliceMode); |
| 415 | #endif//#if _DEBUG | 415 | #endif//#if _DEBUG |
| 416 | return 1; | 416 | return 1; |
| 417 | } | 417 | |
| 418 | // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting | 418 | } |
| 419 | if ( iMbWidth * iMbHeight <= MIN_NUM_MB_PER_SLICE ) | 419 | break; |
| 420 | { | 420 | } |
| 421 | fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE; | 421 | } |
| 422 | fDlp->sMso.sSliceArgument.iSliceNum = 1; | 422 | |
| 423 | break; | 423 | return ParamValidation (pCodingParam); |
| 424 | } | 424 | } |
| 425 | } | 425 | |
| 426 | break; | 426 | /*! |
| 427 | default: | 427 | * \brief acquire count number of layers and NALs based on configurable paramters dependency |
| 428 | { | 428 | * \pParam pCtx sWelsEncCtx* |
| 429 | 429 | * \pParam pParam SWelsSvcCodingParam* | |
| 430 | #if defined (_DEBUG) | 430 | * \pParam pCountLayers pointer of count number of layers indeed |
| 431 | fprintf(stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", pCodingParam->sDependencyLayers[0].sMso.uiSliceMode ); | 431 | * \pParam iCountNals pointer of count number of nals indeed |
| 432 | #endif//#if _DEBUG | 432 | * \return 0 - successful; otherwise failed |
| 433 | return 1; | 433 | */ |
| 434 | 434 | static inline int32_t AcquireLayersNals (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pParam, int32_t* pCountLayers, | |
| 435 | } | 435 | int32_t* pCountNals) { |
| 436 | break; | 436 | int32_t iCountNumLayers = 0; |
| 437 | } | 437 | int32_t iCountNumNals = 0; |
| 438 | } | 438 | int32_t iNumDependencyLayers = 0; |
| 439 | 439 | int32_t iDIndex = 0; | |
| 440 | return ParamValidation(pCodingParam); | 440 | #if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) |
| 441 | } | 441 | int32_t iNumLayersPack = 0; |
| 442 | 442 | #endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | |
| 443 | /*! | 443 | |
| 444 | * \brief acquire count number of layers and NALs based on configurable paramters dependency | 444 | if (NULL == pParam || NULL == ppCtx || NULL == *ppCtx) |
| 445 | * \pParam pCtx sWelsEncCtx* | 445 | return 1; |
| 446 | * \pParam pParam SWelsSvcCodingParam* | 446 | |
| 447 | * \pParam pCountLayers pointer of count number of layers indeed | 447 | iNumDependencyLayers = pParam->iNumDependencyLayer; |
| 448 | * \pParam iCountNals pointer of count number of nals indeed | 448 | |
| 449 | * \return 0 - successful; otherwise failed | 449 | do { |
| 450 | */ | 450 | SDLayerParam* pDLayer = &pParam->sDependencyLayers[iDIndex]; |
| 451 | static inline int32_t AcquireLayersNals( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pParam, int32_t *pCountLayers, int32_t *pCountNals ) | 451 | // pDLayer->ptr_cfg = pParam; |
| 452 | { | 452 | int32_t iOrgNumNals = iCountNumNals; |
| 453 | int32_t iCountNumLayers = 0; | 453 | |
| 454 | int32_t iCountNumNals = 0; | 454 | //Note: Sep. 2010 |
| 455 | int32_t iNumDependencyLayers = 0; | 455 | //Review this part and suggest no change, since the memory over-use |
| 456 | int32_t iDIndex = 0; | 456 | //(1) counts little to the overall performance |
| 457 | #if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | 457 | //(2) should not be critial even under mobile case |
| 458 | int32_t iNumLayersPack = 0; | 458 | if (SM_DYN_SLICE == pDLayer->sMso.uiSliceMode) { |
| 459 | #endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | 459 | iCountNumNals += MAX_SLICES_NUM; |
| 460 | 460 | // plus prefix NALs | |
| 461 | if ( NULL == pParam || NULL == ppCtx || NULL == *ppCtx ) | 461 | if (iDIndex == 0) |
| 462 | return 1; | 462 | iCountNumNals += MAX_SLICES_NUM; |
| 463 | 463 | // MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME ensured at svc_enc_slice_segment.h | |
| 464 | iNumDependencyLayers = pParam->iNumDependencyLayer; | 464 | #if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) |
| 465 | 465 | assert (MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME); | |
| 466 | do { | 466 | // iNumLayersPack += MAX_SLICES_NUM; // do not count it for dynamic slicing mode |
| 467 | SDLayerParam *pDLayer = &pParam->sDependencyLayers[iDIndex]; | 467 | #else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER |
| 468 | // pDLayer->ptr_cfg = pParam; | 468 | assert (iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER); |
| 469 | int32_t iOrgNumNals = iCountNumNals; | 469 | #endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER |
| 470 | 470 | } else { /*if ( SM_SINGLE_SLICE != pDLayer->sMso.uiSliceMode )*/ | |
| 471 | //Note: Sep. 2010 | 471 | const int32_t kiNumOfSlice = GetInitialSliceNum ((pDLayer->iFrameWidth + 0x0f) >> 4, |
| 472 | //Review this part and suggest no change, since the memory over-use | 472 | (pDLayer->iFrameHeight + 0x0f) >> 4, |
| 473 | //(1) counts little to the overall performance | 473 | &pDLayer->sMso); |
| 474 | //(2) should not be critial even under mobile case | 474 | |
| 475 | if ( SM_DYN_SLICE == pDLayer->sMso.uiSliceMode ) | 475 | // NEED check iCountNals value in case multiple slices is used |
| 476 | { | 476 | iCountNumNals += kiNumOfSlice; // for pSlice VCL NALs |
| 477 | iCountNumNals += MAX_SLICES_NUM; | 477 | // plus prefix NALs |
| 478 | // plus prefix NALs | 478 | if (iDIndex == 0) |
| 479 | if ( iDIndex == 0 ) | 479 | iCountNumNals += kiNumOfSlice; |
| 480 | iCountNumNals += MAX_SLICES_NUM; | 480 | #if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) |
| 481 | // MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME ensured at svc_enc_slice_segment.h | 481 | assert (num_of_slice <= MAX_SLICES_NUM && MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME); |
| 482 | #if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | 482 | iNumLayersPack += num_of_slice; |
| 483 | assert(MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME); | 483 | #else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER |
| 484 | // iNumLayersPack += MAX_SLICES_NUM; // do not count it for dynamic slicing mode | 484 | assert (iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER); |
| 485 | #else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER | 485 | #endif//MT_ENALBED && PACKING_ONE_SLICE_PER_LAYER |
| 486 | assert(iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER ); | 486 | if (kiNumOfSlice > MAX_SLICES_NUM) { |
| 487 | #endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | 487 | WelsLog (*ppCtx, WELS_LOG_ERROR, |
| 488 | } | 488 | "AcquireLayersNals(), num_of_slice(%d) > MAX_SLICES_NUM(%d) per (iDid= %d, qid= %d) settings!\n", |
| 489 | else /*if ( SM_SINGLE_SLICE != pDLayer->sMso.uiSliceMode )*/ | 489 | kiNumOfSlice, MAX_SLICES_NUM, iDIndex, 0); |
| 490 | { | 490 | return 1; |
| 491 | const int32_t kiNumOfSlice = GetInitialSliceNum( (pDLayer->iFrameWidth+0x0f)>>4, | 491 | } |
| 492 | (pDLayer->iFrameHeight+0x0f)>>4, | 492 | } |
| 493 | &pDLayer->sMso ); | 493 | #if !defined(MT_ENABLED) || !defined(PACKING_ONE_SLICE_PER_LAYER) |
| 494 | 494 | if (iCountNumNals - iOrgNumNals > MAX_NAL_UNITS_IN_LAYER) { | |
| 495 | // NEED check iCountNals value in case multiple slices is used | 495 | WelsLog (*ppCtx, WELS_LOG_ERROR, |
| 496 | iCountNumNals += kiNumOfSlice; // for pSlice VCL NALs | 496 | "AcquireLayersNals(), num_of_nals(%d) > MAX_NAL_UNITS_IN_LAYER(%d) per (iDid= %d, qid= %d) settings!\n", |
| 497 | // plus prefix NALs | 497 | (iCountNumNals - iOrgNumNals), MAX_NAL_UNITS_IN_LAYER, iDIndex, 0); |
| 498 | if ( iDIndex == 0 ) | 498 | return 1; |
| 499 | iCountNumNals += kiNumOfSlice; | 499 | } |
| 500 | #if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | 500 | #endif//!MT_ENABLED) || !PACKING_ONE_SLICE_PER_LAYER |
| 501 | assert(num_of_slice <= MAX_SLICES_NUM && MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME); | 501 | |
| 502 | iNumLayersPack += num_of_slice; | 502 | iCountNumLayers ++; |
| 503 | #else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER | 503 | |
| 504 | assert(iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER ); | 504 | ++ iDIndex; |
| 505 | #endif//MT_ENALBED && PACKING_ONE_SLICE_PER_LAYER | 505 | } while (iDIndex < iNumDependencyLayers); |
| 506 | if ( kiNumOfSlice > MAX_SLICES_NUM ) | 506 | |
| 507 | { | 507 | iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers << 1) + |
| 508 | WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), num_of_slice(%d) > MAX_SLICES_NUM(%d) per (iDid= %d, qid= %d) settings!\n", | 508 | iCountNumLayers; // plus iCountNumLayers for reserved application |
| 509 | kiNumOfSlice, MAX_SLICES_NUM, iDIndex, 0 ); | 509 | #if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) |
| 510 | return 1; | 510 | iNumLayersPack += 1 + iNumDependencyLayers + (iCountNumLayers << 1); |
| 511 | } | 511 | #endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER |
| 512 | } | 512 | |
| 513 | #if !defined(MT_ENABLED) || !defined(PACKING_ONE_SLICE_PER_LAYER) | 513 | // to check number of layers / nals / slices dependencies, 12/8/2010 |
| 514 | if ( iCountNumNals - iOrgNumNals > MAX_NAL_UNITS_IN_LAYER ) | 514 | #if !defined(MT_ENABLED) |
| 515 | { | 515 | if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) { |
| 516 | WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), num_of_nals(%d) > MAX_NAL_UNITS_IN_LAYER(%d) per (iDid= %d, qid= %d) settings!\n", | 516 | WelsLog (*ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", |
| 517 | (iCountNumNals - iOrgNumNals), MAX_NAL_UNITS_IN_LAYER, iDIndex, 0 ); | 517 | iCountNumLayers, MAX_LAYER_NUM_OF_FRAME); |
| 518 | return 1; | 518 | return 1; |
| 519 | } | 519 | } |
| 520 | #endif//!MT_ENABLED) || !PACKING_ONE_SLICE_PER_LAYER | 520 | #else//MT_ENABLED |
| 521 | 521 | #if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 522 | iCountNumLayers ++; | 522 | if (iNumLayersPack > MAX_LAYER_NUM_OF_FRAME) { |
| 523 | 523 | WelsLog (*ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), num_layers_pack_overall(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", | |
| 524 | ++ iDIndex; | 524 | iNumLayersPack, MAX_LAYER_NUM_OF_FRAME); |
| 525 | } while(iDIndex < iNumDependencyLayers); | 525 | return 1; |
| 526 | 526 | } | |
| 527 | iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers<<1) + iCountNumLayers; // plus iCountNumLayers for reserved application | 527 | #else//!PACKING_ONE_SLICE_PER_LAYER |
| 528 | #if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER) | 528 | if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) { |
| 529 | iNumLayersPack += 1 + iNumDependencyLayers + (iCountNumLayers<<1); | 529 | WelsLog (*ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", |
| 530 | #endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER | 530 | iCountNumLayers, MAX_LAYER_NUM_OF_FRAME); |
| 531 | 531 | return 1; | |
| 532 | // to check number of layers / nals / slices dependencies, 12/8/2010 | 532 | } |
| 533 | #if !defined(MT_ENABLED) | 533 | #endif//PACKING_ONE_SLICE_PER_LAYER |
| 534 | if ( iCountNumLayers > MAX_LAYER_NUM_OF_FRAME ) | 534 | #endif//!MT_ENABLED |
| 535 | { | 535 | |
| 536 | WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", iCountNumLayers, MAX_LAYER_NUM_OF_FRAME ); | 536 | if (NULL != pCountLayers) |
| 537 | return 1; | 537 | *pCountLayers = iCountNumLayers; |
| 538 | } | 538 | if (NULL != pCountNals) |
| 539 | #else//MT_ENABLED | 539 | *pCountNals = iCountNumNals; |
| 540 | #if defined(PACKING_ONE_SLICE_PER_LAYER) | 540 | return 0; |
| 541 | if ( iNumLayersPack > MAX_LAYER_NUM_OF_FRAME ) | 541 | } |
| 542 | { | 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 ); | 543 | /*! |
| 544 | return 1; | 544 | * \brief alloc spatial layers pictures (I420 based source pictures) |
| 545 | } | 545 | */ |
| 546 | #else//!PACKING_ONE_SLICE_PER_LAYER | 546 | int32_t AllocSpatialPictures (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pParam) { |
| 547 | if ( iCountNumLayers > MAX_LAYER_NUM_OF_FRAME ) | 547 | CMemoryAlign* pMa = (*ppCtx)->pMemAlign; |
| 548 | { | 548 | const int32_t kiDlayerCount = pParam->iNumDependencyLayer; |
| 549 | WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", iCountNumLayers, MAX_LAYER_NUM_OF_FRAME ); | 549 | int32_t iDlayerIndex = 0; |
| 550 | return 1; | 550 | |
| 551 | } | 551 | // spatial pictures |
| 552 | #endif//PACKING_ONE_SLICE_PER_LAYER | 552 | iDlayerIndex = 0; |
| 553 | #endif//!MT_ENABLED | 553 | do { |
| 554 | 554 | const int32_t kiPicWidth = pParam->sDependencyLayers[iDlayerIndex].iFrameWidth; | |
| 555 | if ( NULL != pCountLayers ) | 555 | const int32_t kiPicHeight = pParam->sDependencyLayers[iDlayerIndex].iFrameHeight; |
| 556 | *pCountLayers = iCountNumLayers; | 556 | const uint8_t kuiLayerInTemporal = 2 + WELS_MAX (pParam->sDependencyLayers[iDlayerIndex].iHighestTemporalId, 1); |
| 557 | if ( NULL != pCountNals ) | 557 | const uint8_t kuiRefNumInTemporal = kuiLayerInTemporal + pParam->iLTRRefNum; |
| 558 | *pCountNals = iCountNumNals; | 558 | uint8_t i = 0; |
| 559 | return 0; | 559 | |
| 560 | } | 560 | do { |
| 561 | 561 | SPicture* pPic = AllocPicture (pMa, kiPicWidth, kiPicHeight, false); | |
| 562 | /*! | 562 | WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pPic), FreeMemorySvc (ppCtx); *ppCtx = NULL) |
| 563 | * \brief alloc spatial layers pictures (I420 based source pictures) | 563 | (*ppCtx)->pSpatialPic[iDlayerIndex][i] = pPic; |
| 564 | */ | 564 | ++ i; |
| 565 | int32_t AllocSpatialPictures( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pParam ) | 565 | } while (i < kuiRefNumInTemporal); |
| 566 | { | 566 | |
| 567 | CMemoryAlign *pMa = (*ppCtx)->pMemAlign; | 567 | (*ppCtx)->uiSpatialLayersInTemporal[iDlayerIndex] = kuiLayerInTemporal; |
| 568 | const int32_t kiDlayerCount = pParam->iNumDependencyLayer; | 568 | (*ppCtx)->uiSpatialPicNum[iDlayerIndex] = kuiRefNumInTemporal; |
| 569 | int32_t iDlayerIndex = 0; | 569 | ++ iDlayerIndex; |
| 570 | 570 | } while (iDlayerIndex < kiDlayerCount); | |
| 571 | // spatial pictures | 571 | |
| 572 | iDlayerIndex = 0; | 572 | return 0; |
| 573 | do { | 573 | } |
| 574 | const int32_t kiPicWidth = pParam->sDependencyLayers[iDlayerIndex].iFrameWidth; | 574 | |
| 575 | const int32_t kiPicHeight = pParam->sDependencyLayers[iDlayerIndex].iFrameHeight; | 575 | void FreeSpatialPictures (sWelsEncCtx* pCtx) { |
| 576 | const uint8_t kuiLayerInTemporal = 2 + WELS_MAX(pParam->sDependencyLayers[iDlayerIndex].iHighestTemporalId, 1); | 576 | CMemoryAlign* pMa = pCtx->pMemAlign; |
| 577 | const uint8_t kuiRefNumInTemporal = kuiLayerInTemporal + pParam->iLTRRefNum; | 577 | int32_t j = 0; |
| 578 | uint8_t i = 0; | 578 | while (j < pCtx->pSvcParam->iNumDependencyLayer) { |
| 579 | 579 | uint8_t i = 0; | |
| 580 | do { | 580 | uint8_t uiRefNumInTemporal = pCtx->uiSpatialPicNum[j]; |
| 581 | SPicture *pPic = AllocPicture( pMa, kiPicWidth, kiPicHeight, false ); | 581 | |
| 582 | WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pPic), FreeMemorySvc(ppCtx); *ppCtx = NULL ) | 582 | while (i < uiRefNumInTemporal) { |
| 583 | (*ppCtx)->pSpatialPic[iDlayerIndex][i] = pPic; | 583 | if (NULL != pCtx->pSpatialPic[j][i]) { |
| 584 | ++ i; | 584 | FreePicture (pMa, &pCtx->pSpatialPic[j][i]); |
| 585 | } while( i < kuiRefNumInTemporal); | 585 | } |
| 586 | 586 | ++ i; | |
| 587 | (*ppCtx)->uiSpatialLayersInTemporal[iDlayerIndex] = kuiLayerInTemporal; | 587 | } |
| 588 | (*ppCtx)->uiSpatialPicNum[iDlayerIndex] = kuiRefNumInTemporal; | 588 | pCtx->uiSpatialLayersInTemporal[j] = 0; |
| 589 | ++ iDlayerIndex; | 589 | ++ j; |
| 590 | } while( iDlayerIndex < kiDlayerCount ); | 590 | } |
| 591 | 591 | ||
| 592 | return 0; | 592 | } |
| 593 | } | 593 | |
| 594 | 594 | static void InitMbInfo (sWelsEncCtx* pEnc, SMB* pList, SDqLayer* pLayer, const int32_t kiDlayerId, | |
| 595 | void FreeSpatialPictures( sWelsEncCtx *pCtx ) | 595 | const int32_t kiMaxMbNum) { |
| 596 | { | 596 | int32_t iMbWidth = pLayer->iMbWidth; |
| 597 | CMemoryAlign *pMa = pCtx->pMemAlign; | 597 | int32_t iMbHeight = pLayer->iMbHeight; |
| 598 | int32_t j = 0; | 598 | int32_t iIdx; |
| 599 | while( j < pCtx->pSvcParam->iNumDependencyLayer ) | 599 | int32_t iMbNum = iMbWidth * iMbHeight; |
| 600 | { | 600 | SSliceCtx* pSliceCtx = pLayer->pSliceEncCtx; |
| 601 | uint8_t i = 0; | 601 | uint32_t uiNeighborAvail; |
| 602 | uint8_t uiRefNumInTemporal = pCtx->uiSpatialPicNum[j]; | 602 | const int32_t kiOffset = (kiDlayerId & 0x01) * kiMaxMbNum; |
| 603 | 603 | SMVUnitXY (*pLayerMvUnitBlock4x4)[MB_BLOCK4x4_NUM] = (SMVUnitXY (*)[MB_BLOCK4x4_NUM]) ( | |
| 604 | while( i < uiRefNumInTemporal ) | 604 | &pEnc->pMvUnitBlock4x4[MB_BLOCK4x4_NUM * kiOffset]); |
| 605 | { | 605 | int8_t (*pLayerRefIndexBlock8x8)[MB_BLOCK8x8_NUM] = (int8_t (*)[MB_BLOCK8x8_NUM]) ( |
| 606 | if ( NULL != pCtx->pSpatialPic[j][i] ) | 606 | &pEnc->pRefIndexBlock4x4[MB_BLOCK8x8_NUM * kiOffset]); |
| 607 | { | 607 | |
| 608 | FreePicture( pMa, &pCtx->pSpatialPic[j][i] ); | 608 | for (iIdx = 0; iIdx < iMbNum; iIdx++) { |
| 609 | } | 609 | BOOL_T bLeft; |
| 610 | ++ i; | 610 | BOOL_T bTop; |
| 611 | } | 611 | BOOL_T bLeftTop; |
| 612 | pCtx->uiSpatialLayersInTemporal[j] = 0; | 612 | BOOL_T bRightTop; |
| 613 | ++ j; | 613 | int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY; |
| 614 | } | 614 | uint8_t uiSliceIdc; |
| 615 | 615 | ||
| 616 | } | 616 | pList[iIdx].iMbX = pEnc->pStrideTab->pMbIndexX[kiDlayerId][iIdx]; |
| 617 | 617 | pList[iIdx].iMbY = pEnc->pStrideTab->pMbIndexY[kiDlayerId][iIdx]; | |
| 618 | static void InitMbInfo(sWelsEncCtx * pEnc, SMB * pList, SDqLayer * pLayer, const int32_t kiDlayerId, const int32_t kiMaxMbNum ) | 618 | pList[iIdx].iMbXY = iIdx; |
| 619 | { | 619 | |
| 620 | int32_t iMbWidth = pLayer->iMbWidth; | 620 | uiSliceIdc = WelsMbToSliceIdc (pSliceCtx, iIdx); |
| 621 | int32_t iMbHeight = pLayer->iMbHeight; | 621 | iLeftXY = iIdx - 1; |
| 622 | int32_t iIdx; | 622 | iTopXY = iIdx - iMbWidth; |
| 623 | int32_t iMbNum = iMbWidth * iMbHeight; | 623 | iLeftTopXY = iTopXY - 1; |
| 624 | SSliceCtx *pSliceCtx= pLayer->pSliceEncCtx; | 624 | iRightTopXY = iTopXY + 1; |
| 625 | uint32_t uiNeighborAvail; | 625 | |
| 626 | const int32_t kiOffset = (kiDlayerId & 0x01) * kiMaxMbNum; | 626 | bLeft = (pList[iIdx].iMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc (pSliceCtx, iLeftXY)); |
| 627 | SMVUnitXY (*pLayerMvUnitBlock4x4)[MB_BLOCK4x4_NUM] = (SMVUnitXY(*)[MB_BLOCK4x4_NUM])(&pEnc->pMvUnitBlock4x4[MB_BLOCK4x4_NUM*kiOffset]); | 627 | bTop = (pList[iIdx].iMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pSliceCtx, iTopXY)); |
| 628 | int8_t (*pLayerRefIndexBlock8x8)[MB_BLOCK8x8_NUM] = (int8_t(*)[MB_BLOCK8x8_NUM])(&pEnc->pRefIndexBlock4x4[MB_BLOCK8x8_NUM*kiOffset]); | 628 | bLeftTop = (pList[iIdx].iMbX > 0) && (pList[iIdx].iMbY > 0) && (uiSliceIdc == |
| 629 | 629 | WelsMbToSliceIdc (pSliceCtx, iLeftTopXY)); | |
| 630 | for( iIdx = 0; iIdx<iMbNum; iIdx++ ){ | 630 | bRightTop = (pList[iIdx].iMbX < (iMbWidth - 1)) && (pList[iIdx].iMbY > 0) && (uiSliceIdc == |
| 631 | BOOL_T bLeft; | 631 | WelsMbToSliceIdc (pSliceCtx, iRightTopXY)); |
| 632 | BOOL_T bTop; | 632 | |
| 633 | BOOL_T bLeftTop; | 633 | uiNeighborAvail = 0; |
| 634 | BOOL_T bRightTop; | 634 | if (bLeft) { |
| 635 | int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY; | 635 | uiNeighborAvail |= LEFT_MB_POS; |
| 636 | uint8_t uiSliceIdc; | 636 | } |
| 637 | 637 | if (bTop) { | |
| 638 | pList[iIdx].iMbX = pEnc->pStrideTab->pMbIndexX[kiDlayerId][iIdx]; | 638 | uiNeighborAvail |= TOP_MB_POS; |
| 639 | pList[iIdx].iMbY = pEnc->pStrideTab->pMbIndexY[kiDlayerId][iIdx]; | 639 | } |
| 640 | pList[iIdx].iMbXY = iIdx; | 640 | if (bLeftTop) { |
| 641 | 641 | uiNeighborAvail |= TOPLEFT_MB_POS; | |
| 642 | uiSliceIdc = WelsMbToSliceIdc(pSliceCtx, iIdx); | 642 | } |
| 643 | iLeftXY = iIdx - 1; | 643 | if (bRightTop) { |
| 644 | iTopXY = iIdx - iMbWidth; | 644 | uiNeighborAvail |= TOPRIGHT_MB_POS; |
| 645 | iLeftTopXY = iTopXY - 1; | 645 | } |
| 646 | iRightTopXY = iTopXY + 1; | 646 | pList[iIdx].uiSliceIdc = uiSliceIdc; // merge from svc_hd_opt_b for multiple slices coding |
| 647 | 647 | pList[iIdx].uiNeighborAvail = uiNeighborAvail; | |
| 648 | bLeft = (pList[iIdx].iMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iLeftXY)); | 648 | uiNeighborAvail = 0; |
| 649 | bTop = (pList[iIdx].iMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iTopXY)); | 649 | if (pList[iIdx].iMbX >= BASE_MV_MB_NMB) |
| 650 | bLeftTop = (pList[iIdx].iMbX > 0) && (pList[iIdx].iMbY > 0) && (uiSliceIdc == | 650 | uiNeighborAvail |= LEFT_MB_POS; |
| 651 | WelsMbToSliceIdc(pSliceCtx, iLeftTopXY)); | 651 | if (pList[iIdx].iMbX <= (iMbWidth - 1 - BASE_MV_MB_NMB)) |
| 652 | bRightTop = (pList[iIdx].iMbX < (iMbWidth-1)) && (pList[iIdx].iMbY > 0) && (uiSliceIdc == | 652 | uiNeighborAvail |= RIGHT_MB_POS; |
| 653 | WelsMbToSliceIdc(pSliceCtx, iRightTopXY)); | 653 | if (pList[iIdx].iMbY >= BASE_MV_MB_NMB) |
| 654 | 654 | uiNeighborAvail |= TOP_MB_POS; | |
| 655 | uiNeighborAvail = 0; | 655 | if (pList[iIdx].iMbY <= (iMbHeight - 1 - BASE_MV_MB_NMB)) |
| 656 | if( bLeft ){ | 656 | uiNeighborAvail |= BOTTOM_MB_POS; |
| 657 | uiNeighborAvail |= LEFT_MB_POS; | 657 | |
| 658 | } | 658 | pList[iIdx].sMv = pLayerMvUnitBlock4x4[iIdx]; |
| 659 | if( bTop ){ | 659 | pList[iIdx].pRefIndex = pLayerRefIndexBlock8x8[iIdx]; |
| 660 | uiNeighborAvail |= TOP_MB_POS; | 660 | pList[iIdx].pSadCost = &pEnc->pSadCostMb[iIdx]; |
| 661 | } | 661 | pList[iIdx].pIntra4x4PredMode = &pEnc->pIntra4x4PredModeBlocks[iIdx * INTRA_4x4_MODE_NUM]; |
| 662 | if( bLeftTop ){ | 662 | pList[iIdx].pNonZeroCount = &pEnc->pNonZeroCountBlocks[iIdx * MB_LUMA_CHROMA_BLOCK4x4_NUM]; |
| 663 | uiNeighborAvail |= TOPLEFT_MB_POS; | 663 | } |
| 664 | } | 664 | } |
| 665 | if( bRightTop ){ | 665 | |
| 666 | uiNeighborAvail |= TOPRIGHT_MB_POS; | 666 | |
| 667 | } | 667 | int32_t InitMbListD (sWelsEncCtx** ppCtx) { |
| 668 | pList[iIdx].uiSliceIdc = uiSliceIdc; // merge from svc_hd_opt_b for multiple slices coding | 668 | int32_t iNumDlayer = (*ppCtx)->pSvcParam->iNumDependencyLayer; |
| 669 | pList[iIdx].uiNeighborAvail = uiNeighborAvail; | 669 | int32_t iMbSize[MAX_DEPENDENCY_LAYER] = { 0 }; |
| 670 | uiNeighborAvail = 0; | 670 | int32_t iOverallMbNum = 0; |
| 671 | if(pList[iIdx].iMbX >= BASE_MV_MB_NMB) | 671 | int32_t iMbWidth = 0; |
| 672 | uiNeighborAvail |= LEFT_MB_POS; | 672 | int32_t iMbHeight = 0; |
| 673 | if(pList[iIdx].iMbX <= (iMbWidth-1-BASE_MV_MB_NMB)) | 673 | int32_t i; |
| 674 | uiNeighborAvail |= RIGHT_MB_POS; | 674 | |
| 675 | if (pList[iIdx].iMbY >= BASE_MV_MB_NMB) | 675 | if (iNumDlayer > MAX_DEPENDENCY_LAYER) |
| 676 | uiNeighborAvail |= TOP_MB_POS; | 676 | return 1; |
| 677 | if(pList[iIdx].iMbY <= (iMbHeight-1-BASE_MV_MB_NMB)) | 677 | |
| 678 | uiNeighborAvail |= BOTTOM_MB_POS; | 678 | for (i = 0; i < iNumDlayer; i++) { |
| 679 | 679 | iMbWidth = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameWidth + 15) >> 4; | |
| 680 | pList[iIdx].sMv = pLayerMvUnitBlock4x4[iIdx]; | 680 | iMbHeight = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameHeight + 15) >> 4; |
| 681 | pList[iIdx].pRefIndex = pLayerRefIndexBlock8x8[iIdx]; | 681 | iMbSize[i] = iMbWidth * iMbHeight; |
| 682 | pList[iIdx].pSadCost = &pEnc->pSadCostMb[iIdx]; | 682 | iOverallMbNum += iMbSize[i]; |
| 683 | pList[iIdx].pIntra4x4PredMode = &pEnc->pIntra4x4PredModeBlocks[iIdx*INTRA_4x4_MODE_NUM]; | 683 | } |
| 684 | pList[iIdx].pNonZeroCount = &pEnc->pNonZeroCountBlocks[iIdx*MB_LUMA_CHROMA_BLOCK4x4_NUM]; | 684 | |
| 685 | } | 685 | (*ppCtx)->ppMbListD = static_cast<SMB**> ((*ppCtx)->pMemAlign->WelsMalloc (iNumDlayer * sizeof (SMB*), "ppMbListD")); |
| 686 | } | 686 | (*ppCtx)->ppMbListD[0] = NULL; |
| 687 | 687 | WELS_VERIFY_RETURN_PROC_IF (1, (*ppCtx)->ppMbListD == NULL, FreeMemorySvc (ppCtx)); | |
| 688 | 688 | (*ppCtx)->ppMbListD[0] = static_cast<SMB*> ((*ppCtx)->pMemAlign->WelsMallocz (iOverallMbNum * sizeof (SMB), | |
| 689 | int32_t InitMbListD( sWelsEncCtx ** ppCtx) | 689 | "ppMbListD[0]")); |
| 690 | { | 690 | WELS_VERIFY_RETURN_PROC_IF (1, (*ppCtx)->ppMbListD[0] == NULL, FreeMemorySvc (ppCtx)); |
| 691 | int32_t iNumDlayer = (*ppCtx)->pSvcParam->iNumDependencyLayer; | 691 | (*ppCtx)->ppDqLayerList[0]->sMbDataP = (*ppCtx)->ppMbListD[0]; |
| 692 | int32_t iMbSize[MAX_DEPENDENCY_LAYER] = { 0 }; | 692 | InitMbInfo (*ppCtx, (*ppCtx)->ppMbListD[0], (*ppCtx)->ppDqLayerList[0], 0, iMbSize[iNumDlayer - 1]); |
| 693 | int32_t iOverallMbNum = 0; | 693 | for (i = 1; i < iNumDlayer; i++) { |
| 694 | int32_t iMbWidth = 0; | 694 | (*ppCtx)->ppMbListD[i] = (*ppCtx)->ppMbListD[i - 1] + iMbSize[i - 1]; |
| 695 | int32_t iMbHeight= 0; | 695 | (*ppCtx)->ppDqLayerList[i]->sMbDataP = (*ppCtx)->ppMbListD[i]; |
| 696 | int32_t i; | 696 | InitMbInfo (*ppCtx, (*ppCtx)->ppMbListD[i], (*ppCtx)->ppDqLayerList[i], i, iMbSize[iNumDlayer - 1]); |
| 697 | 697 | } | |
| 698 | if ( iNumDlayer > MAX_DEPENDENCY_LAYER ) | 698 | |
| 699 | return 1; | 699 | return 0; |
| 700 | 700 | } | |
| 701 | for( i=0;i<iNumDlayer;i++ ){ | 701 | |
| 702 | iMbWidth = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameWidth + 15)>>4; | 702 | int32_t AllocMbCacheAligned (SMbCache* pMbCache, CMemoryAlign* pMa) { |
| 703 | iMbHeight = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameHeight + 15)>>4; | 703 | pMbCache->pCoeffLevel = (int16_t*)pMa->WelsMalloc (MB_COEFF_LIST_SIZE * sizeof (int16_t), "pMbCache->pCoeffLevel"); |
| 704 | iMbSize[i] = iMbWidth * iMbHeight; | 704 | WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pCoeffLevel)); |
| 705 | iOverallMbNum += iMbSize[i]; | 705 | pMbCache->pMemPredMb = (uint8_t*)pMa->WelsMalloc (2 * 256 * sizeof (uint8_t), "pMbCache->pMemPredMb"); |
| 706 | } | 706 | WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pMemPredMb)); |
| 707 | 707 | pMbCache->pSkipMb = (uint8_t*)pMa->WelsMalloc (384 * sizeof (uint8_t), "pMbCache->pSkipMb"); | |
| 708 | (*ppCtx)->ppMbListD = static_cast<SMB **>((*ppCtx)->pMemAlign->WelsMalloc(iNumDlayer * sizeof(SMB *), "ppMbListD")); | 708 | WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pSkipMb)); |
| 709 | (*ppCtx)->ppMbListD[0] = NULL; | 709 | pMbCache->pMemPredBlk4 = (uint8_t*)pMa->WelsMalloc (2 * 16 * sizeof (uint8_t), "pMbCache->pMemPredBlk4"); |
| 710 | WELS_VERIFY_RETURN_PROC_IF(1, (*ppCtx)->ppMbListD==NULL, FreeMemorySvc(ppCtx)); | 710 | WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pMemPredBlk4)); |
| 711 | (*ppCtx)->ppMbListD[0] = static_cast<SMB*>((*ppCtx)->pMemAlign->WelsMallocz(iOverallMbNum * sizeof(SMB), "ppMbListD[0]")); | 711 | pMbCache->pBufferInterPredMe = (uint8_t*)pMa->WelsMalloc (4 * 640 * sizeof (uint8_t), "pMbCache->pBufferInterPredMe"); |
| 712 | WELS_VERIFY_RETURN_PROC_IF(1, (*ppCtx)->ppMbListD[0]==NULL, FreeMemorySvc(ppCtx)); | 712 | WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pBufferInterPredMe)); |
| 713 | (*ppCtx)->ppDqLayerList[0]->sMbDataP = (*ppCtx)->ppMbListD[0]; | 713 | pMbCache->pPrevIntra4x4PredModeFlag = (bool_t*)pMa->WelsMalloc (16 * sizeof (bool_t), |
| 714 | InitMbInfo(*ppCtx, (*ppCtx)->ppMbListD[0], (*ppCtx)->ppDqLayerList[0], 0, iMbSize[iNumDlayer-1]); | 714 | "pMbCache->pPrevIntra4x4PredModeFlag"); |
| 715 | for( i=1;i<iNumDlayer;i++ ){ | 715 | WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pPrevIntra4x4PredModeFlag)); |
| 716 | (*ppCtx)->ppMbListD[i] = (*ppCtx)->ppMbListD[i-1] + iMbSize[i-1]; | 716 | pMbCache->pRemIntra4x4PredModeFlag = (int8_t*)pMa->WelsMalloc (16 * sizeof (int8_t), |
| 717 | (*ppCtx)->ppDqLayerList[i]->sMbDataP = (*ppCtx)->ppMbListD[i]; | 717 | "pMbCache->pRemIntra4x4PredModeFlag"); |
| 718 | InitMbInfo(*ppCtx, (*ppCtx)->ppMbListD[i], (*ppCtx)->ppDqLayerList[i], i, iMbSize[iNumDlayer-1]); | 718 | WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pRemIntra4x4PredModeFlag)); |
| 719 | } | 719 | pMbCache->pDct = (SDCTCoeff*)pMa->WelsMalloc (sizeof (SDCTCoeff), "pMbCache->pDct"); |
| 720 | 720 | WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pDct)); | |
| 721 | return 0; | 721 | return 0; |
| 722 | } | 722 | } |
| 723 | 723 | ||
| 724 | int32_t AllocMbCacheAligned( SMbCache *pMbCache, CMemoryAlign *pMa ) | 724 | void FreeMbCache (SMbCache* pMbCache, CMemoryAlign* pMa) { |
| 725 | { | 725 | if (NULL != pMbCache->pCoeffLevel) { |
| 726 | pMbCache->pCoeffLevel = (int16_t *)pMa->WelsMalloc(MB_COEFF_LIST_SIZE*sizeof(int16_t), "pMbCache->pCoeffLevel"); | 726 | pMa->WelsFree (pMbCache->pCoeffLevel, "pMbCache->pCoeffLevel"); |
| 727 | WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pCoeffLevel)); | 727 | pMbCache->pCoeffLevel = NULL; |
| 728 | pMbCache->pMemPredMb = (uint8_t *)pMa->WelsMalloc(2*256*sizeof(uint8_t), "pMbCache->pMemPredMb"); | 728 | } |
| 729 | WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pMemPredMb)); | 729 | if (NULL != pMbCache->pMemPredMb) { |
| 730 | pMbCache->pSkipMb = (uint8_t *)pMa->WelsMalloc(384*sizeof(uint8_t), "pMbCache->pSkipMb"); | 730 | pMa->WelsFree (pMbCache->pMemPredMb, "pMbCache->pMemPredMb"); |
| 731 | WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pSkipMb)); | 731 | pMbCache->pMemPredMb = NULL; |
| 732 | pMbCache->pMemPredBlk4 = (uint8_t *)pMa->WelsMalloc(2*16*sizeof(uint8_t), "pMbCache->pMemPredBlk4"); | 732 | } |
| 733 | WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pMemPredBlk4)); | 733 | if (NULL != pMbCache->pSkipMb) { |
| 734 | pMbCache->pBufferInterPredMe = (uint8_t *)pMa->WelsMalloc(4*640*sizeof(uint8_t), "pMbCache->pBufferInterPredMe"); | 734 | pMa->WelsFree (pMbCache->pSkipMb, "pMbCache->pSkipMb"); |
| 735 | WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pBufferInterPredMe)); | 735 | pMbCache->pSkipMb = NULL; |
| 736 | pMbCache->pPrevIntra4x4PredModeFlag = (bool_t *)pMa->WelsMalloc(16*sizeof(bool_t), "pMbCache->pPrevIntra4x4PredModeFlag"); | 736 | } |
| 737 | WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pPrevIntra4x4PredModeFlag)); | 737 | if (NULL != pMbCache->pMemPredBlk4) { |
| 738 | pMbCache->pRemIntra4x4PredModeFlag = (int8_t *)pMa->WelsMalloc(16*sizeof(int8_t), "pMbCache->pRemIntra4x4PredModeFlag"); | 738 | pMa->WelsFree (pMbCache->pMemPredBlk4, "pMbCache->pMemPredBlk4"); |
| 739 | WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pRemIntra4x4PredModeFlag)); | 739 | pMbCache->pMemPredBlk4 = NULL; |
| 740 | pMbCache->pDct = (SDCTCoeff *)pMa->WelsMalloc(sizeof(SDCTCoeff), "pMbCache->pDct"); | 740 | } |
| 741 | WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pDct)); | 741 | if (NULL != pMbCache->pBufferInterPredMe) { |
| 742 | return 0; | 742 | pMa->WelsFree (pMbCache->pBufferInterPredMe, "pMbCache->pBufferInterPredMe"); |
| 743 | } | 743 | pMbCache->pBufferInterPredMe = NULL; |
| 744 | 744 | } | |
| 745 | void FreeMbCache( SMbCache *pMbCache, CMemoryAlign *pMa ) | 745 | if (NULL != pMbCache->pPrevIntra4x4PredModeFlag) { |
| 746 | { | 746 | pMa->WelsFree (pMbCache->pPrevIntra4x4PredModeFlag, "pMbCache->pPrevIntra4x4PredModeFlag"); |
| 747 | if ( NULL != pMbCache->pCoeffLevel ) | 747 | pMbCache->pPrevIntra4x4PredModeFlag = NULL; |
| 748 | { | 748 | } |
| 749 | pMa->WelsFree( pMbCache->pCoeffLevel, "pMbCache->pCoeffLevel" ); | 749 | if (NULL != pMbCache->pRemIntra4x4PredModeFlag) { |
| 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 | ||
3283 more lines aren’t shown here.