[x265] [PATCH 2/3] Memory Leak Fix: Part 2

Jean-Baptiste Kempf jb at videolan.org
Sun Nov 10 10:53:25 UTC 2024


Hard coding a max string size is pretty bad and will fail.

On Sun, 10 Nov 2024, at 06:40, Pavan Tarun Chakka Venkata wrote:
> From e33b7bc78be5d49dd510435981231a63f1c76aec Mon Sep 17 00:00:00 2001
> From: Min Chen <chenm003 at 163.com>
> Date: Sat, 9 Nov 2024 12:58:49 +0530
> Subject: [PATCH 2/3] Memory Leak Fix: Part 2
> 
> ---
>  source/CMakeLists.txt            |   2 +-
>  source/abrEncApp.cpp             |   9 +-
>  source/common/param.cpp          | 140 ++++++++++++++++---------------
>  source/common/temporalfilter.cpp |   7 ++
>  source/common/temporalfilter.h   |   2 +-
>  source/common/threadpool.cpp     |   4 +-
>  source/encoder/analysis.cpp      |   6 +-
>  source/encoder/api.cpp           |  17 +++-
>  source/encoder/encoder.cpp       | 111 +++++++++++-------------
>  source/encoder/encoder.h         |   1 +
>  source/encoder/frameencoder.cpp  |  12 ++-
>  source/encoder/framefilter.cpp   |   8 +-
>  source/encoder/ratecontrol.cpp   |   4 +-
>  source/encoder/search.cpp        |   4 +-
>  source/encoder/slicetype.cpp     |  16 ++--
>  source/x265.cpp                  |  24 ++++--
>  source/x265.h                    |  28 ++++---
>  source/x265cli.cpp               |   7 +-
>  source/x265cli.h                 |   8 +-
>  19 files changed, 210 insertions(+), 200 deletions(-)
> 
> diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
> index 310683909..14f6ccc49 100755
> --- a/source/CMakeLists.txt
> +++ b/source/CMakeLists.txt
> @@ -31,7 +31,7 @@ option(NATIVE_BUILD "Target the build CPU" OFF)
>  option(STATIC_LINK_CRT "Statically link C and C++ runtimes for release builds" OFF)
>  mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)
>  # X265_BUILD must be incremented each time the public API is changed
> -set(X265_BUILD 213)
> +set(X265_BUILD 214)
>  configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
>                 "${PROJECT_BINARY_DIR}/x265.def")
>  configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
> diff --git a/source/abrEncApp.cpp b/source/abrEncApp.cpp
> index ebdd3b3ba..a56e14cde 100644
> --- a/source/abrEncApp.cpp
> +++ b/source/abrEncApp.cpp
> @@ -282,8 +282,8 @@ namespace X265_NS {
>  
>          m_param->analysisLoadReuseLevel = m_cliopt.loadLevel;
>          m_param->analysisSaveReuseLevel = m_cliopt.saveLevel;
> -        m_param->analysisSave = m_cliopt.saveLevel ? "save.dat" : NULL;
> -        m_param->analysisLoad = m_cliopt.loadLevel ? "load.dat" : NULL;
> +        strcpy(m_param->analysisSave, m_cliopt.saveLevel ? "save.dat" : "");
> +        strcpy(m_param->analysisLoad, m_cliopt.loadLevel ? "load.dat" : "");
>          m_param->bUseAnalysisFile = 0;
>  
>          if (m_cliopt.loadLevel)
> @@ -599,7 +599,7 @@ ret:
>              x265_picture* pic_recon;
>              x265_picture pic_out[MAX_LAYERS];
>  
> -            pic_recon = (m_cliopt.recon[0] || m_param->analysisSave || m_param->analysisLoad || pts_queue || reconPlay || m_param->csvLogLevel) ? pic_out : NULL;
> +            pic_recon = (m_cliopt.recon[0] || strlen(m_param->analysisSave) || strlen(m_param->analysisLoad) || pts_queue || reconPlay || m_param->csvLogLevel) ? pic_out : NULL;
>              uint32_t inFrameCount = 0;
>              uint32_t outFrameCount = 0;
>              x265_nal *p_nal;
> @@ -895,7 +895,7 @@ ret:
>              delete reconPlay;
>  
>              api->encoder_get_stats(m_encoder, &stats, sizeof(stats));
> -            if (m_param->csvfn && !b_ctrl_c)
> +            if (strlen(m_param->csvfn) && !b_ctrl_c)
>  #if ENABLE_LIBVMAF
>                  api->vmaf_encoder_log(m_encoder, m_cliopt.argCnt, m_cliopt.argString, m_cliopt.param, vmafdata);
>  #else
> @@ -919,7 +919,6 @@ ret:
>              if (b_ctrl_c)
>                  general_log(m_param, NULL, X265_LOG_INFO, "aborted at input frame %d, output frame %d in %s\n",
>                      m_cliopt.seek + inFrameCount, stats.encodedPictureCount, profileName);
> -            if(m_param->numaPools)    free((char*)m_param->numaPools);
>              api->param_free(m_param);
>  
>              X265_FREE(errorBuf);
> diff --git a/source/common/param.cpp b/source/common/param.cpp
> index 1beb3c056..010721315 100755
> --- a/source/common/param.cpp
> +++ b/source/common/param.cpp
> @@ -94,6 +94,7 @@ namespace X265_NS {
>  x265_param *x265_param_alloc()
>  {
>      x265_param* param = (x265_param*)x265_malloc(sizeof(x265_param));
> +    memset(param, 0, sizeof(x265_param));
>  #ifdef SVT_HEVC
>      param->svtHevcParam = (EB_H265_ENC_CONFIGURATION*)x265_malloc(sizeof(EB_H265_ENC_CONFIGURATION));
>  #endif
> @@ -151,8 +152,8 @@ void x265_param_default(x265_param* param)
>  
>      param->logLevel = X265_LOG_INFO;
>      param->csvLogLevel = 0;
> -    param->csvfn = NULL;
> -    param->rc.lambdaFileName = NULL;
> +    param->csvfn[0] = 0;
> +    param->rc.lambdaFileName[0] = 0;
>      param->bLogCuStats = 0;
>      param->decodedPictureHashSEI = 0;
>  
> @@ -279,9 +280,9 @@ void x265_param_default(x265_param* param)
>      param->analysisReuseMode = 0; /*DEPRECATED*/
>      param->analysisMultiPassRefine = 0;
>      param->analysisMultiPassDistortion = 0;
> -    param->analysisReuseFileName = NULL;
> -    param->analysisSave = NULL;
> -    param->analysisLoad = NULL;
> +    param->analysisReuseFileName[0] = 0;
> +    param->analysisSave[0] = 0;
> +    param->analysisLoad[0] = 0;
>      param->bIntraInBFrames = 1;
>      param->bLossless = 0;
>      param->bCULossless = 0;
> @@ -317,8 +318,8 @@ void x265_param_default(x265_param* param)
>      param->rc.bStatRead = 0;
>      param->rc.bStatWrite = 0;
>      param->rc.dataShareMode = X265_SHARE_MODE_FILE;
> -    param->rc.statFileName = NULL;
> -    param->rc.sharedMemName = NULL;
> +    param->rc.statFileName[0] = 0;
> +    param->rc.sharedMemName[0] = 0;
>      param->rc.bEncFocusedFramesOnly = 0;
>      param->rc.complexityBlur = 20;
>      param->rc.qblur = 0.5;
> @@ -362,7 +363,7 @@ void x265_param_default(x265_param* param)
>      param->maxLuma = PIXEL_MAX;
>      param->log2MaxPocLsb = 8;
>      param->maxSlices = 1;
> -    param->videoSignalTypePreset = NULL;
> +    param->videoSignalTypePreset[0] = 0;
>  
>      /*Conformance window*/
>      param->confWinRightOffset = 0;
> @@ -379,7 +380,7 @@ void x265_param_default(x265_param* param)
>      param->analysisReuseLevel = 0;  /*DEPRECATED*/
>      param->analysisSaveReuseLevel = 0;
>      param->analysisLoadReuseLevel = 0;
> -    param->toneMapFile = NULL;
> +    param->toneMapFile[0] = 0;
>      param->bDhdr10opt = 0;
>      param->dolbyProfile = 0;
>      param->bCTUInfo = 0;
> @@ -396,7 +397,7 @@ void x265_param_default(x265_param* param)
>      param->bDisableLookahead = 0;
>      param->bCopyPicToFrame = 1;
>      param->maxAUSizeFactor = 1;
> -    param->naluFile = NULL;
> +    param->naluFile[0] = 0;
>  
>      /* DCT Approximations */
>      param->bLowPassDct = 0;
> @@ -842,7 +843,7 @@ int x265_zone_param_parse(x265_param* p, const char* name, const char* value)
>              p->rdoqLevel = 0;
>      }
>      OPT("b-intra") p->bIntraInBFrames = atobool(value);
> -    OPT("scaling-list") p->scalingLists = strdup(value);
> +    OPT("scaling-list") snprintf(p->scalingLists, X265_MAX_STRING_SIZE, "%s", value);
>      OPT("crf")
>      {
>          p->rc.rfConstant = atof(value);
> @@ -1294,13 +1295,13 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)
>          p->rc.bStatRead = pass & 2;
>          p->rc.dataShareMode = X265_SHARE_MODE_FILE;
>      }
> -    OPT("stats") p->rc.statFileName = strdup(value);
> -    OPT("scaling-list") p->scalingLists = strdup(value);
> -    OPT2("pools", "numa-pools") p->numaPools = strdup(value);
> -    OPT("lambda-file") p->rc.lambdaFileName = strdup(value);
> -    OPT("analysis-reuse-file") p->analysisReuseFileName = strdup(value);
> +    OPT("stats") snprintf(p->rc.statFileName, X265_MAX_STRING_SIZE, "%s", value);
> +    OPT("scaling-list") snprintf(p->scalingLists, X265_MAX_STRING_SIZE, "%s", value);
> +    OPT2("pools", "numa-pools") snprintf(p->numaPools, X265_MAX_STRING_SIZE, "%s", value);
> +    OPT("lambda-file") snprintf(p->rc.lambdaFileName, X265_MAX_STRING_SIZE, "%s", value);
> +    OPT("analysis-reuse-file") snprintf(p->analysisReuseFileName, X265_MAX_STRING_SIZE, "%s", value);
>      OPT("qg-size") p->rc.qgSize = atoi(value);
> -    OPT("master-display") p->masteringDisplayColorVolume = strdup(value);
> +    OPT("master-display") snprintf(p->masteringDisplayColorVolume, X265_MAX_STRING_SIZE, "%s", value);
>      OPT("max-cll") bError |= sscanf(value, "%hu,%hu", &p->maxCLL, &p->maxFALL) != 2;
>      OPT("min-luma") p->minLuma = (uint16_t)atoi(value);
>      OPT("max-luma") p->maxLuma = (uint16_t)atoi(value);
> @@ -1312,7 +1313,7 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)
>      if (bExtraParams)
>      {
>          if (0) ;
> -        OPT("csv") p->csvfn = strdup(value);
> +        OPT("csv") snprintf(p->csvfn, X265_MAX_STRING_SIZE, "%s", value);
>          OPT("csv-log-level") p->csvLogLevel = atoi(value);
>          OPT("qpmin") p->rc.qpMin = atoi(value);
>          OPT("analyze-src-pics") p->bSourceReferenceEstimation = atobool(value);
> @@ -1357,7 +1358,7 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)
>          OPT("hdr-opt") p->bHDR10Opt = atobool(value); /*DEPRECATED*/
>          OPT("hdr10-opt") p->bHDR10Opt = atobool(value);
>          OPT("limit-sao") p->bLimitSAO = atobool(value);
> -        OPT("dhdr10-info") p->toneMapFile = strdup(value);
> +        OPT("dhdr10-info") snprintf(p->toneMapFile, X265_MAX_STRING_SIZE, "%s", value);
>          OPT("dhdr10-opt") p->bDhdr10opt = atobool(value);
>          OPT("idr-recovery-sei") p->bEmitIDRRecoverySEI = atobool(value);
>          OPT("const-vbv") p->rc.bEnableConstVbv = atobool(value);
> @@ -1374,15 +1375,15 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)
>          OPT("copy-pic") p->bCopyPicToFrame = atobool(value);
>          OPT("refine-analysis-type")
>          {
> -            if (strcmp(strdup(value), "avc") == 0)
> +            if (strcmp((value), "avc") == 0)
>              {
>                  p->bAnalysisType = AVC_INFO;
>              }
> -            else if (strcmp(strdup(value), "hevc") == 0)
> +            else if (strcmp((value), "hevc") == 0)
>              {
>                  p->bAnalysisType = HEVC_INFO;
>              }
> -            else if (strcmp(strdup(value), "off") == 0)
> +            else if (strcmp((value), "off") == 0)
>              {
>                  p->bAnalysisType = DEFAULT;
>              }
> @@ -1392,8 +1393,8 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)
>              }
>          }
>          OPT("gop-lookahead") p->gopLookahead = atoi(value);
> -        OPT("analysis-save") p->analysisSave = strdup(value);
> -        OPT("analysis-load") p->analysisLoad = strdup(value);
> +        OPT("analysis-save") snprintf(p->analysisSave, X265_MAX_STRING_SIZE, "%s", value);
> +        OPT("analysis-load") snprintf(p->analysisLoad, X265_MAX_STRING_SIZE, "%s", value);
>          OPT("radl") p->radl = atoi(value);
>          OPT("max-ausize-factor") p->maxAUSizeFactor = atof(value);
>          OPT("dynamic-refine") p->bDynamicRefine = atobool(value);
> @@ -1402,7 +1403,7 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)
>          OPT("pic-struct") p->pictureStructure = atoi(value);
>          OPT("chunk-start") p->chunkStart = atoi(value);
>          OPT("chunk-end") p->chunkEnd = atoi(value);
> -        OPT("nalu-file") p->naluFile = strdup(value);
> +        OPT("nalu-file") snprintf(p->naluFile, X265_MAX_STRING_SIZE, "%s", value);
>          OPT("dolby-vision-profile")
>          {
>              if (atof(value) < 10)
> @@ -1478,7 +1479,7 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)
>          OPT("vbv-live-multi-pass") p->bliveVBV2pass = atobool(value);
>          OPT("min-vbv-fullness") p->minVbvFullness = atof(value);
>          OPT("max-vbv-fullness") p->maxVbvFullness = atof(value);
> -        OPT("video-signal-type-preset") p->videoSignalTypePreset = strdup(value);
> +        OPT("video-signal-type-preset") snprintf(p->videoSignalTypePreset, X265_MAX_STRING_SIZE, "%s", value);
>          OPT("eob") p->bEnableEndOfBitstream = atobool(value);
>          OPT("eos") p->bEnableEndOfSequence = atobool(value);
>          /* Film grain characterstics model filename */
> @@ -1866,11 +1867,11 @@ int x265_check_params(x265_param* param)
>            "Constant QP is incompatible with 2pass");
>      CHECK(param->rc.bStrictCbr && (param->rc.bitrate <= 0 || param->rc.vbvBufferSize <=0),
>            "Strict-cbr cannot be applied without specifying target bitrate or vbv bufsize");
> -    CHECK(param->analysisSave && (param->analysisSaveReuseLevel < 0 || param->analysisSaveReuseLevel > 10),
> +    CHECK(strlen(param->analysisSave) && (param->analysisSaveReuseLevel < 0 || param->analysisSaveReuseLevel > 10),
>          "Invalid analysis save refine level. Value must be between 1 and 10 (inclusive)");
> -    CHECK(param->analysisLoad && (param->analysisLoadReuseLevel < 0 || param->analysisLoadReuseLevel > 10),
> +    CHECK(strlen(param->analysisLoad) && (param->analysisLoadReuseLevel < 0 || param->analysisLoadReuseLevel > 10),
>          "Invalid analysis load refine level. Value must be between 1 and 10 (inclusive)");
> -    CHECK(param->analysisLoad && (param->mvRefine < 1 || param->mvRefine > 3),
> +    CHECK(strlen(param->analysisLoad) && (param->mvRefine < 1 || param->mvRefine > 3),
>          "Invalid mv refinement level. Value must be between 1 and 3 (inclusive)");
>      CHECK(param->scaleFactor > 2, "Invalid scale-factor. Supports factor <= 2");
>      CHECK(param->rc.qpMax < QP_MIN || param->rc.qpMax > QP_MAX_MAX,
> @@ -1948,7 +1949,7 @@ int x265_check_params(x265_param* param)
>          "SEA motion search does not support resolutions greater than 480p in 32 bit build");
>  #endif
>  
> -    if (param->masteringDisplayColorVolume || param->maxFALL || param->maxCLL)
> +    if (strlen(param->masteringDisplayColorVolume) || param->maxFALL || param->maxCLL)
>          param->bEmitHDR10SEI = 1;
>  
>      bool isSingleSEI = (param->bRepeatHeaders
> @@ -1958,8 +1959,8 @@ int x265_check_params(x265_param* param)
>                       || param->bEmitIDRRecoverySEI
>                     || !!param->interlaceMode
>                       || param->preferredTransferCharacteristics > 1
> -                     || param->toneMapFile
> -                     || param->naluFile);
> +                     || strlen(param->toneMapFile)
> +                     || strlen(param->naluFile));
>  
>      if (!isSingleSEI && param->bSingleSeiNal)
>      {
> @@ -1990,7 +1991,7 @@ int x265_check_params(x265_param* param)
>          CHECK((param->internalCsp != X265_CSP_I420), "Alpha encode supported only with i420a colorspace");
>          CHECK((param->internalBitDepth > 10), "BitDepthConstraint must be 8 and 10  for Scalable main profile");
>          CHECK((param->analysisMultiPassDistortion || param->analysisMultiPassRefine), "Alpha encode doesnot support multipass feature");
> -        CHECK((param->analysisSave || param->analysisLoad), "Alpha encode doesnot support analysis save and load  feature");
> +        CHECK((strlen(param->analysisSave) || strlen(param->analysisLoad)), "Alpha encode doesnot support analysis save and load  feature");
>      }
>  #endif
>  #if ENABLE_MULTIVIEW
> @@ -1999,7 +2000,7 @@ int x265_check_params(x265_param* param)
>      {
>          CHECK(param->internalBitDepth != 8, "BitDepthConstraint must be 8 for Multiview main profile");
>          CHECK(param->analysisMultiPassDistortion || param->analysisMultiPassRefine, "Multiview encode doesnot support multipass feature");
> -        CHECK(param->analysisSave || param->analysisLoad, "Multiview encode doesnot support analysis save and load feature");
> +        CHECK(strlen(param->analysisSave) || strlen(param->analysisLoad), "Multiview encode doesnot support analysis save and load feature");
>      }
>  #endif
>  #if ENABLE_SCC_EXT
> @@ -2202,11 +2203,11 @@ char *x265_param2string(x265_param* p, int padx, int pady)
>  {
>      char *buf, *s;
>      size_t bufSize = 4000 + p->rc.zoneCount * 64;
> -    if (p->numaPools)
> +    if (strlen(p->numaPools))
>          bufSize += strlen(p->numaPools);
> -    if (p->masteringDisplayColorVolume)
> +    if (strlen(p->masteringDisplayColorVolume))
>          bufSize += strlen(p->masteringDisplayColorVolume);
> -    if (p->videoSignalTypePreset)
> +    if (strlen(p->videoSignalTypePreset))
>          bufSize += strlen(p->videoSignalTypePreset);
>  
>      buf = s = X265_MALLOC(char, bufSize);
> @@ -2217,7 +2218,7 @@ char *x265_param2string(x265_param* p, int padx, int pady)
>  
>      s += snprintf(s, bufSize - (s - buf), "cpuid=%d", p->cpuid);
>      s += snprintf(s, bufSize - (s - buf), " frame-threads=%d", p->frameNumThreads);
> -    if (p->numaPools)
> +    if (strlen(p->numaPools))
>          s += snprintf(s, bufSize - (s - buf), " numa-pools=%s", p->numaPools);
>      BOOL(p->bEnableWavefront, "wpp");
>      BOOL(p->bDistributeModeAnalysis, "pmode");
> @@ -2225,7 +2226,7 @@ char *x265_param2string(x265_param* p, int padx, int pady)
>      BOOL(p->bEnablePsnr, "psnr");
>      BOOL(p->bEnableSsim, "ssim");
>      s += snprintf(s, bufSize - (s - buf), " log-level=%d", p->logLevel);
> -    if (p->csvfn)
> +    if (strlen(p->csvfn))
>          s += snprintf(s, bufSize - (s - buf), " csv csv-log-level=%d", p->csvLogLevel);
>      s += snprintf(s, bufSize - (s - buf), " bitdepth=%d", p->internalBitDepth);
>      s += snprintf(s, bufSize - (s - buf), " input-csp=%d", p->internalCsp);
> @@ -2402,7 +2403,7 @@ char *x265_param2string(x265_param* p, int padx, int pady)
>          s += snprintf(s, bufSize - (s - buf), " left=%d top=%d right=%d bottom=%d",
>          p->vui.defDispWinLeftOffset, p->vui.defDispWinTopOffset,
>          p->vui.defDispWinRightOffset, p->vui.defDispWinBottomOffset);
> -    if (p->masteringDisplayColorVolume)
> +    if (strlen(p->masteringDisplayColorVolume))
>          s += snprintf(s, bufSize - (s - buf), " master-display=%s", p->masteringDisplayColorVolume);
>      if (p->bEmitCLL)
>          s += snprintf(s, bufSize - (s - buf), " cll=%hu,%hu", p->maxCLL, p->maxFALL);
> @@ -2422,9 +2423,9 @@ char *x265_param2string(x265_param* p, int padx, int pady)
>      BOOL(p->bHDR10Opt, "hdr10-opt");
>      BOOL(p->bDhdr10opt, "dhdr10-opt");
>      BOOL(p->bEmitIDRRecoverySEI, "idr-recovery-sei");
> -    if (p->analysisSave)
> +    if (strlen(p->analysisSave))
>          s += snprintf(s, bufSize - (s - buf), " analysis-save");
> -    if (p->analysisLoad)
> +    if (strlen(p->analysisLoad))
>          s += snprintf(s, bufSize - (s - buf), " analysis-load");
>      s += snprintf(s, bufSize - (s - buf), " analysis-reuse-level=%d", p->analysisReuseLevel);
>      s += snprintf(s, bufSize - (s - buf), " analysis-save-reuse-level=%d", p->analysisSaveReuseLevel);
> @@ -2474,7 +2475,7 @@ char *x265_param2string(x265_param* p, int padx, int pady)
>  
>  bool parseLambdaFile(x265_param* param)
>  {
> -    if (!param->rc.lambdaFileName)
> +    if (!strlen(param->rc.lambdaFileName))
>          return false;
>  
>      FILE *lfn = x265_fopen(param->rc.lambdaFileName, "r");
> @@ -2692,8 +2693,8 @@ void x265_copy_params(x265_param* dst, x265_param* src)
>      dst->mcstfFrameRange = src->mcstfFrameRange;
>      dst->cpuid = src->cpuid;
>      dst->frameNumThreads = src->frameNumThreads;
> -    if (src->numaPools) dst->numaPools = strdup(src->numaPools);
> -    else dst->numaPools = NULL;
> +    if (strlen(src->numaPools)) snprintf(dst->numaPools, X265_MAX_STRING_SIZE, "%s", src->numaPools);
> +    else dst->numaPools[0] = 0;
>  
>      dst->bEnableWavefront = src->bEnableWavefront;
>      dst->bDistributeModeAnalysis = src->bDistributeModeAnalysis;
> @@ -2703,8 +2704,8 @@ void x265_copy_params(x265_param* dst, x265_param* src)
>      dst->bEnableSsim = src->bEnableSsim;
>      dst->logLevel = src->logLevel;
>      dst->csvLogLevel = src->csvLogLevel;
> -    if (src->csvfn) dst->csvfn = strdup(src->csvfn);
> -    else dst->csvfn = NULL;
> +    if (strlen(src->csvfn)) snprintf(dst->csvfn, X265_MAX_STRING_SIZE, "%s", src->csvfn);
> +    else dst->csvfn[0] = 0;
>      dst->internalBitDepth = src->internalBitDepth;
>      dst->sourceBitDepth = src->sourceBitDepth;
>      dst->internalCsp = src->internalCsp;
> @@ -2754,8 +2755,8 @@ void x265_copy_params(x265_param* dst, x265_param* src)
>      dst->bEnableTransformSkip = src->bEnableTransformSkip;
>      dst->noiseReductionInter = src->noiseReductionInter;
>      dst->noiseReductionIntra = src->noiseReductionIntra;
> -    if (src->scalingLists) dst->scalingLists = strdup(src->scalingLists);
> -    else dst->scalingLists = NULL;
> +    if (strlen(src->scalingLists)) snprintf(dst->scalingLists, X265_MAX_STRING_SIZE, "%s", src->scalingLists);
> +    else dst->scalingLists[0] = 0;
>      dst->bEnableStrongIntraSmoothing = src->bEnableStrongIntraSmoothing;
>      dst->bEnableConstrainedIntra = src->bEnableConstrainedIntra;
>      dst->maxNumMergeCand = src->maxNumMergeCand;
> @@ -2797,8 +2798,8 @@ void x265_copy_params(x265_param* dst, x265_param* src)
>      dst->psyRdoq = src->psyRdoq;
>      dst->bEnableRdRefine = src->bEnableRdRefine;
>      dst->analysisReuseMode = src->analysisReuseMode;
> -    if (src->analysisReuseFileName) dst->analysisReuseFileName=strdup(src->analysisReuseFileName);
> -    else dst->analysisReuseFileName = NULL;
> +    if (strlen(src->analysisReuseFileName)) snprintf(dst->analysisReuseFileName, X265_MAX_STRING_SIZE, "%s", src->analysisReuseFileName);
> +    else dst->analysisReuseFileName[0] = 0;
>      dst->bLossless = src->bLossless;
>      dst->cbQpOffset = src->cbQpOffset;
>      dst->crQpOffset = src->crQpOffset;
> @@ -2827,10 +2828,10 @@ void x265_copy_params(x265_param* dst, x265_param* src)
>      dst->rc.bStatWrite = src->rc.bStatWrite;
>      dst->rc.bStatRead = src->rc.bStatRead;
>      dst->rc.dataShareMode = src->rc.dataShareMode;
> -    if (src->rc.statFileName) dst->rc.statFileName=strdup(src->rc.statFileName);
> -    else dst->rc.statFileName = NULL;
> -    if (src->rc.sharedMemName) dst->rc.sharedMemName = strdup(src->rc.sharedMemName);
> -    else dst->rc.sharedMemName = NULL;
> +    if (strlen(src->rc.statFileName)) snprintf(dst->rc.statFileName, X265_MAX_STRING_SIZE, "%s", src->rc.statFileName);
> +    else dst->rc.statFileName[0] = 0;
> +    if (strlen(src->rc.sharedMemName)) snprintf(dst->rc.sharedMemName, X265_MAX_STRING_SIZE, "%s", src->rc.sharedMemName);
> +    else dst->rc.sharedMemName[0] = 0;
>      dst->rc.qblur = src->rc.qblur;
>      dst->rc.complexityBlur = src->rc.complexityBlur;
>      dst->rc.bEnableSlowFirstPass = src->rc.bEnableSlowFirstPass;
> @@ -2864,8 +2865,8 @@ void x265_copy_params(x265_param* dst, x265_param* src)
>      else
>          dst->rc.zones = NULL;
>  
> -    if (src->rc.lambdaFileName) dst->rc.lambdaFileName = strdup(src->rc.lambdaFileName);
> -    else dst->rc.lambdaFileName = NULL;
> +    if (strlen(src->rc.lambdaFileName)) snprintf(dst->rc.lambdaFileName, X265_MAX_STRING_SIZE, "%s", src->rc.lambdaFileName);
> +    else dst->rc.lambdaFileName[0] = 0;
>      dst->rc.bStrictCbr = src->rc.bStrictCbr;
>      dst->rc.qgSize = src->rc.qgSize;
>      dst->rc.bEnableGrain = src->rc.bEnableGrain;
> @@ -2896,8 +2897,8 @@ void x265_copy_params(x265_param* dst, x265_param* src)
>      dst->vui.defDispWinRightOffset = src->vui.defDispWinRightOffset;
>      dst->vui.defDispWinTopOffset = src->vui.defDispWinTopOffset;
>  
> -    if (src->masteringDisplayColorVolume) dst->masteringDisplayColorVolume=strdup( src->masteringDisplayColorVolume);
> -    else dst->masteringDisplayColorVolume = NULL;
> +    if (strlen(src->masteringDisplayColorVolume)) snprintf(dst->masteringDisplayColorVolume, X265_MAX_STRING_SIZE, "%s", src->masteringDisplayColorVolume);
> +    else dst->masteringDisplayColorVolume[0] = 0;
>      dst->maxLuma = src->maxLuma;
>      dst->minLuma = src->minLuma;
>      dst->bEmitCLL = src->bEmitCLL;
> @@ -2926,8 +2927,8 @@ void x265_copy_params(x265_param* dst, x265_param* src)
>      dst->analysisSaveReuseLevel = src->analysisSaveReuseLevel;
>      dst->analysisLoadReuseLevel = src->analysisLoadReuseLevel;
>      dst->bLimitSAO = src->bLimitSAO;
> -    if (src->toneMapFile) dst->toneMapFile = strdup(src->toneMapFile);
> -    else dst->toneMapFile = NULL;
> +    if (strlen(src->toneMapFile)) snprintf(dst->toneMapFile, X265_MAX_STRING_SIZE, "%s", src->toneMapFile);
> +    else dst->toneMapFile[0] = 0;
>      dst->bDhdr10opt = src->bDhdr10opt;
>      dst->bCTUInfo = src->bCTUInfo;
>      dst->bUseRcStats = src->bUseRcStats;
> @@ -2949,10 +2950,10 @@ void x265_copy_params(x265_param* dst, x265_param* src)
>      dst->vbvEndFrameAdjust = src->vbvEndFrameAdjust;
>      dst->bAnalysisType = src->bAnalysisType;
>      dst->bCopyPicToFrame = src->bCopyPicToFrame;
> -    if (src->analysisSave) dst->analysisSave=strdup(src->analysisSave);
> -    else dst->analysisSave = NULL;
> -    if (src->analysisLoad) dst->analysisLoad=strdup(src->analysisLoad);
> -    else dst->analysisLoad = NULL;
> +    if (strlen(src->analysisSave)) snprintf(dst->analysisSave, X265_MAX_STRING_SIZE, "%s", src->analysisSave);
> +    else dst->analysisSave[0] = 0;
> +    if (strlen(src->analysisLoad)) snprintf(dst->analysisLoad, X265_MAX_STRING_SIZE, "%s", src->analysisLoad);
> +    else dst->analysisLoad[0] = 0;
>      dst->gopLookahead = src->gopLookahead;
>      dst->radl = src->radl;
>      dst->selectiveSAO = src->selectiveSAO;
> @@ -2962,8 +2963,8 @@ void x265_copy_params(x265_param* dst, x265_param* src)
>      dst->bSingleSeiNal = src->bSingleSeiNal;
>      dst->chunkStart = src->chunkStart;
>      dst->chunkEnd = src->chunkEnd;
> -    if (src->naluFile) dst->naluFile=strdup(src->naluFile);
> -    else dst->naluFile = NULL;
> +    if (src->naluFile) snprintf(dst->naluFile, X265_MAX_STRING_SIZE, "%s", src->naluFile);
> +    else dst->naluFile[0] = 0;
>      dst->scaleFactor = src->scaleFactor;
>      dst->ctuDistortionRefine = src->ctuDistortionRefine;
>      dst->bEnableHRDConcatFlag = src->bEnableHRDConcatFlag;
> @@ -3001,8 +3002,8 @@ void x265_copy_params(x265_param* dst, x265_param* src)
>      dst->bEnableSCC = src->bEnableSCC;
>  #endif
>  
> -    if (src->videoSignalTypePreset) dst->videoSignalTypePreset = strdup(src->videoSignalTypePreset);
> -    else dst->videoSignalTypePreset = NULL;
> +    if (strlen(src->videoSignalTypePreset)) snprintf(dst->videoSignalTypePreset, X265_MAX_STRING_SIZE, "%s", src->videoSignalTypePreset);
> +    else dst->videoSignalTypePreset[0] = 0;
>  #ifdef SVT_HEVC
>      memcpy(dst->svtHevcParam, src->svtHevcParam, sizeof(EB_H265_ENC_CONFIGURATION));
>  #endif
> @@ -3236,6 +3237,7 @@ int svt_param_parse(x265_param* param, const char* name, const char* value)
>                  svtHevcParam->logicalProcessors = atoi(temp1);
>              }
>          }
> +        free(pools);
>      }
>      OPT("high-tier") svtHevcParam->tier = x265_atobool(value, bError);
>      OPT("qpmin") svtHevcParam->minQpAllowed = atoi(value);
> diff --git a/source/common/temporalfilter.cpp b/source/common/temporalfilter.cpp
> index 215feaa0f..75b7f2188 100644
> --- a/source/common/temporalfilter.cpp
> +++ b/source/common/temporalfilter.cpp
> @@ -153,6 +153,13 @@ TemporalFilter::TemporalFilter()
>      m_motionVectorFactor = 16;
>  }
>  
> +TemporalFilter::~TemporalFilter()
> +{
> +    if (m_metld)
> +        delete m_metld;
> +    predPUYuv.destroy();
> +}
> +
>  void TemporalFilter::init(const x265_param* param)
>  {
>      m_param = param;
> diff --git a/source/common/temporalfilter.h b/source/common/temporalfilter.h
> index 723644633..bc7109b40 100644
> --- a/source/common/temporalfilter.h
> +++ b/source/common/temporalfilter.h
> @@ -118,7 +118,7 @@ namespace X265_NS {
>      {
>      public:
>          TemporalFilter();
> -        ~TemporalFilter() {}
> +        ~TemporalFilter();
>  
>          void init(const x265_param* param);
>  
> diff --git a/source/common/threadpool.cpp b/source/common/threadpool.cpp
> index ab6bd0d43..b3505e5c0 100644
> --- a/source/common/threadpool.cpp
> +++ b/source/common/threadpool.cpp
> @@ -302,7 +302,7 @@ ThreadPool* ThreadPool::allocThreadPools(x265_param* p, int& numPools, bool isTh
>       * For windows because threads can't be allocated to live across sockets
>       * changing the default behavior to be per-socket pools -- FIXME */
>  #if defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WIN7 || HAVE_LIBNUMA
> -    if (!p->numaPools || (strcmp(p->numaPools, "NULL") == 0 || strcmp(p->numaPools, "*") == 0 || strcmp(p->numaPools, "") == 0))
> +    if (!strlen(p->numaPools) || (strcmp(p->numaPools, "NULL") == 0 || strcmp(p->numaPools, "*") == 0 || strcmp(p->numaPools, "") == 0))
>      {
>           char poolString[50] = "";
>           for (int i = 0; i < numNumaNodes; i++)
> @@ -317,7 +317,7 @@ ThreadPool* ThreadPool::allocThreadPools(x265_param* p, int& numPools, bool isTh
>           x265_param_parse(p, "pools", poolString);
>       }
>  #endif
> -    if (p->numaPools && *p->numaPools)
> +    if (strlen(p->numaPools))
>      {
>          const char *nodeStr = p->numaPools;
>          for (int i = 0; i < numNumaNodes; i++)
> diff --git a/source/encoder/analysis.cpp b/source/encoder/analysis.cpp
> index 6c72283f3..da5aeca77 100644
> --- a/source/encoder/analysis.cpp
> +++ b/source/encoder/analysis.cpp
> @@ -203,7 +203,7 @@ Mode& Analysis::compressCTU(CUData& ctu, Frame& frame, const CUGeom& cuGeom, con
>      }
>      
>      int reuseLevel = X265_MAX(m_param->analysisSaveReuseLevel, m_param->analysisLoadReuseLevel);
> -    if ((m_param->analysisSave || m_param->analysisLoad) && m_slice->m_sliceType != I_SLICE && reuseLevel > 1 && reuseLevel < 10)
> +    if ((strlen(m_param->analysisSave) || strlen(m_param->analysisLoad)) && m_slice->m_sliceType != I_SLICE && reuseLevel > 1 && reuseLevel < 10)
>      {
>          int numPredDir = m_slice->isInterP() ? 1 : 2;
>          m_reuseInterDataCTU = m_frame->m_analysisData.interData;
> @@ -217,7 +217,7 @@ Mode& Analysis::compressCTU(CUData& ctu, Frame& frame, const CUGeom& cuGeom, con
>              m_reusePartSize = &m_reuseInterDataCTU->partSize[ctu.m_cuAddr * ctu.m_numPartitions];
>              m_reuseMergeFlag = &m_reuseInterDataCTU->mergeFlag[ctu.m_cuAddr * ctu.m_numPartitions];
>          }
> -        if (m_param->analysisSave && !m_param->analysisLoad)
> +        if (strlen(m_param->analysisSave) && !strlen(m_param->analysisLoad))
>              for (int i = 0; i < X265_MAX_PRED_MODE_PER_CTU * numPredDir; i++)
>                  m_reuseRef[i] = -1;
>      }
> @@ -4130,7 +4130,7 @@ int Analysis::calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom, int3
>      double qp = baseQp >= 0 ? baseQp : curEncData.m_cuStat[ctu.m_cuAddr].baseQp;
>      bool bCuTreeOffset = IS_REFERENCED(m_frame) && m_param->rc.cuTree && !complexCheck;
>  
> -    if ((m_param->analysisMultiPassDistortion && m_param->rc.bStatRead) || (m_param->ctuDistortionRefine && m_param->analysisLoad))
> +    if ((m_param->analysisMultiPassDistortion && m_param->rc.bStatRead) || (m_param->ctuDistortionRefine && strlen(m_param->analysisLoad)))
>      {
>          x265_analysis_distortion_data* distortionData = m_frame->m_analysisData.distortionData;
>          if ((distortionData->threshold[ctu.m_cuAddr] < 0.9 || distortionData->threshold[ctu.m_cuAddr] > 1.1)
> diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp
> index 5d2a951e5..abcb2113c 100644
> --- a/source/encoder/api.cpp
> +++ b/source/encoder/api.cpp
> @@ -204,6 +204,8 @@ x265_encoder *x265_encoder_open(x265_param *p)
>          }
>      }
>  
> +    // Need free zone because follow up Memcpy will broken all of pointer
> +    x265_zone_free(zoneParam);
>      memcpy(zoneParam, param, sizeof(x265_param));
>      for (int i = 0; i < param->rc.zonefileCount; i++)
>      {
> @@ -211,7 +213,7 @@ x265_encoder *x265_encoder_open(x265_param *p)
>      }
>  
>      /* Try to open CSV file handle */
> -    if (encoder->m_param->csvfn)
> +    if (strlen(encoder->m_param->csvfn))
>      {
>          encoder->m_param->csvfpt = x265_csvlog_open(encoder->m_param);
>          if (!encoder->m_param->csvfpt)
> @@ -221,6 +223,7 @@ x265_encoder *x265_encoder_open(x265_param *p)
>          }
>      }
>  
> +    encoder->m_templateParam = param;
>      encoder->m_latestParam = latestParam;
>      encoder->m_zoneParam = zoneParam;
>      x265_copy_params(latestParam, param);
> @@ -309,7 +312,7 @@ int x265_encoder_reconfig(x265_encoder* enc, x265_param* param_in)
>          return -1;
>      x265_param save;
>      Encoder* encoder = static_cast<Encoder*>(enc);
> -    if (encoder->m_param->csvfn == NULL && param_in->csvfpt != NULL)
> +    if (strlen(encoder->m_param->csvfn) && param_in->csvfpt != NULL)
>           encoder->m_param->csvfpt = param_in->csvfpt;
>      if (encoder->m_latestParam->forceFlush != param_in->forceFlush)
>          return encoder->reconfigureParam(encoder->m_latestParam, param_in);
> @@ -327,18 +330,20 @@ int x265_encoder_reconfig(x265_encoder* enc, x265_param* param_in)
>      {
>          /* reconfigure failed, recover saved param set */
>          x265_copy_params(encoder->m_latestParam, &save);
> +        x265_zone_free(&save);
>          ret = -1;
>      }
>      else
>      {
>          encoder->configure(encoder->m_latestParam);
> -        if (encoder->m_latestParam->scalingLists && encoder->m_latestParam->scalingLists != encoder->m_param->scalingLists)
> +        if (strlen(encoder->m_latestParam->scalingLists) && strcmp(encoder->m_latestParam->scalingLists, encoder->m_param->scalingLists))
>          {
>              if (encoder->m_param->bRepeatHeaders)
>              {
>                  if (encoder->m_scalingList.parseScalingList(encoder->m_latestParam->scalingLists))
>                  {
>                      x265_copy_params(encoder->m_latestParam, &save);
> +                    x265_zone_free(&save);
>                      return -1;
>                  }
>                  encoder->m_scalingList.setupQuantMatrices(encoder->m_param->internalCsp);
> @@ -347,6 +352,7 @@ int x265_encoder_reconfig(x265_encoder* enc, x265_param* param_in)
>              {
>                  x265_log(encoder->m_param, X265_LOG_ERROR, "Repeat headers is turned OFF, cannot reconfigure scalinglists\n");
>                  x265_copy_params(encoder->m_latestParam, &save);
> +                x265_zone_free(&save);
>                  return -1;
>              }
>          }
> @@ -373,6 +379,7 @@ int x265_encoder_reconfig(x265_encoder* enc, x265_param* param_in)
>      /* Zones support modifying num of Refs. Requires determining level at each zone start*/
>      if (encoder->m_param->rc.zonefileCount)
>          determineLevel(*encoder->m_latestParam, encoder->m_vps);
> +    x265_zone_free(&save);
>      return ret;
>  }
>  
> @@ -1009,7 +1016,7 @@ void x265_picture_init(x265_param *param, x265_picture *pic)
>      pic->picStruct = 0;
>      pic->vbvEndFlag = 0;
>  
> -    if ((param->analysisSave || param->analysisLoad) || (param->bAnalysisType == AVC_INFO))
> +    if ((strlen(param->analysisSave) || strlen(param->analysisLoad)) || (param->bAnalysisType == AVC_INFO))
>      {
>          uint32_t widthInCU = (param->sourceWidth + param->maxCUSize - 1) >> param->maxLog2CUSize;
>          uint32_t heightInCU = (param->sourceHeight + param->maxCUSize - 1) >> param->maxLog2CUSize;
> @@ -1041,6 +1048,8 @@ void x265_zone_free(x265_param *param)
>      {
>          for (int i = 0; i < param->rc.zonefileCount; i++)
>              x265_free(param->rc.zones[i].zoneParam);
> +        param->rc.zonefileCount = 0;
> +        param->rc.zoneCount = 0;
>          x265_free(param->rc.zones);
>      }
>  }
> diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
> index 5f784e72b..d1d12e91c 100644
> --- a/source/encoder/encoder.cpp
> +++ b/source/encoder/encoder.cpp
> @@ -138,6 +138,7 @@ Encoder::Encoder()
>      m_outputCount = 0;
>      m_param = NULL;
>      m_latestParam = NULL;
> +    m_templateParam = NULL;
>      m_threadPool = NULL;
>      m_analysisFileIn = NULL;
>      m_analysisFileOut = NULL;
> @@ -255,7 +256,7 @@ void Encoder::create()
>          p->bEnableWavefront = 0;
>      }
>  
> -    bool allowPools = !p->numaPools || strcmp(p->numaPools, "none");
> +    bool allowPools = !strlen(p->numaPools) || strcmp(p->numaPools, "none");
>  
>      // Trim the thread pool if --wpp, --pme, and --pmode are disabled
>      if (!p->bEnableWavefront && !p->bDistributeModeAnalysis && !p->bDistributeMotionEstimation && !p->lookaheadSlices)
> @@ -336,7 +337,7 @@ void Encoder::create()
>          m_aborted = true;
>          return;
>      }
> -    else if (!m_param->scalingLists || !strcmp(m_param->scalingLists, "off"))
> +    else if (!strlen(m_param->scalingLists) || !strcmp(m_param->scalingLists, "off"))
>          m_scalingList.m_bEnabled = false;
>      else if (!strcmp(m_param->scalingLists, "default"))
>          m_scalingList.setDefaultScalingList();
> @@ -478,7 +479,7 @@ void Encoder::create()
>          m_aborted = true;
>  
>      initRefIdx();
> -    if (m_param->analysisSave && m_param->bUseAnalysisFile)
> +    if (strlen(m_param->analysisSave) && m_param->bUseAnalysisFile)
>      {
>          char* temp = strcatFilename(m_param->analysisSave, ".temp");
>          if (!temp)
> @@ -498,7 +499,7 @@ void Encoder::create()
>      if (m_param->analysisMultiPassRefine || m_param->analysisMultiPassDistortion)
>      {
>          const char* name = m_param->analysisReuseFileName;
> -        if (!name)
> +        if (!strlen(name))
>              name = defaultAnalysisFileName;
>          if (m_param->rc.bStatWrite)
>          {
> @@ -550,7 +551,7 @@ void Encoder::create()
>  
>      m_nalList.m_annexB = !!m_param->bAnnexB;
>  
> -    if (m_param->naluFile)
> +    if (strlen(m_param->naluFile))
>      {
>          m_naluFile = x265_fopen(m_param->naluFile, "r");
>          if (!m_naluFile)
> @@ -951,19 +952,16 @@ void Encoder::destroy()
>  
>      if (m_latestParam != NULL && m_latestParam != m_param)
>      {
> -        if (m_latestParam->scalingLists != m_param->scalingLists)
> -            free((char*)m_latestParam->scalingLists);
> -        if (m_latestParam->numaPools != m_param->numaPools)
> -            free((char*)m_latestParam->numaPools);
> -
>          PARAM_NS::x265_param_free(m_latestParam);
>      }
>      if (m_zoneParam != NULL && m_zoneParam != m_param) {
> -        if (m_zoneParam->numaPools != m_param->numaPools)
> -            free((char*)m_zoneParam->numaPools);
> -
>          PARAM_NS::x265_param_free(m_zoneParam);
>      }
> +    if (m_templateParam != NULL && m_templateParam != m_param) {
> +        // TODO: we don't free zone here because it is overwrite into m_zoneParam in x265_encoder_open
> +        m_templateParam->rc.zonefileCount = m_templateParam->rc.zoneCount = 0;
> +        PARAM_NS::x265_param_free(m_templateParam);
> +    }
>      if (m_analysisFileIn)
>          fclose(m_analysisFileIn);
>  
> @@ -971,8 +969,8 @@ void Encoder::destroy()
>      {
>          int bError = 1;
>          fclose(m_analysisFileOut);
> -        const char* name = m_param->analysisSave ? m_param->analysisSave : m_param->analysisReuseFileName;
> -        if (!name)
> +        const char* name = strlen(m_param->analysisSave) ? m_param->analysisSave : m_param->analysisReuseFileName;
> +        if (!strlen(name))
>              name = defaultAnalysisFileName;
>          char* temp = strcatFilename(name, ".temp");
>          if (temp)
> @@ -1000,19 +998,6 @@ void Encoder::destroy()
>      {
>          if (m_param->csvfpt)
>              fclose(m_param->csvfpt);
> -        /* release string arguments that were strdup'd */
> -        free((char*)m_param->rc.lambdaFileName);
> -        free((char*)m_param->rc.statFileName);
> -        free((char*)m_param->rc.sharedMemName);
> -        free((char*)m_param->analysisReuseFileName);
> -        free((char*)m_param->scalingLists);
> -        free((char*)m_param->csvfn);
> -        free((char*)m_param->numaPools);
> -        free((char*)m_param->masteringDisplayColorVolume);
> -        free((char*)m_param->toneMapFile);
> -        free((char*)m_param->analysisSave);
> -        free((char*)m_param->analysisLoad);
> -        free((char*)m_param->videoSignalTypePreset);
>          PARAM_NS::x265_param_free(m_param);
>      }
>  }
> @@ -1509,7 +1494,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
>  
>      if (*m_exportedPic)
>      {
> -        if (!m_param->bUseAnalysisFile && m_param->analysisSave)
> +        if (!m_param->bUseAnalysisFile && strlen(m_param->analysisSave))
>              x265_free_analysis_data(m_param, &m_exportedPic[0]->m_analysisData);
>  
>          for (int i = 0; i < m_param->numLayers; i++)
> @@ -1801,7 +1786,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
>  
>          /* In analysisSave mode, x265_analysis_data is allocated in inputPic and inFrame points to this */
>          /* Load analysis data before lookahead->addPicture, since sliceType has been decided */
> -        if (m_param->analysisLoad)
> +        if (strlen(m_param->analysisLoad))
>          {
>              /* reads analysis data for the frame and allocates memory based on slicetype */
>              static int paramBytes = CONF_OFFSET_BYTES;
> @@ -1992,7 +1977,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
>                  x265_frame_stats* frameData = NULL;
>  
>                  /* Free up inputPic->analysisData since it has already been used */
> -                if ((m_param->analysisLoad && !m_param->analysisSave) || ((m_param->bAnalysisType == AVC_INFO) && slice->m_sliceType != I_SLICE))
> +                if ((strlen(m_param->analysisLoad) && !strlen(m_param->analysisSave)) || ((m_param->bAnalysisType == AVC_INFO) && slice->m_sliceType != I_SLICE))
>                      x265_free_analysis_data(m_param, &outFrame->m_analysisData);
>                  if (pic_out)
>                  {
> @@ -2020,7 +2005,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
>                      }
>  
>                      /* Dump analysis data from pic_out to file in save mode and free */
> -                    if (m_param->analysisSave)
> +                    if (strlen(m_param->analysisSave))
>                      {
>                          pic_out[sLayer].analysisData.poc = pic_out[sLayer].poc;
>                          pic_out[sLayer].analysisData.sliceType = pic_out[sLayer].sliceType;
> @@ -2140,7 +2125,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
>  
>                  if ((m_outputCount + 1) >= m_param->chunkStart)
>                      finishFrameStats(outFrame, curEncoder, frameData, m_pocLast, sLayer);
> -                if (m_param->analysisSave)
> +                if (strlen(m_param->analysisSave))
>                  {
>                      pic_out[sLayer].analysisData.frameBits = frameData->bits;
>                      if (!slice->isIntra())
> @@ -2334,7 +2319,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
>                  int baseViewType = frameEnc[0]->m_lowres.sliceType;
>                  frameEnc[layer]->m_encData->m_slice->m_origSliceType = IS_X265_TYPE_B(baseViewType) ? B_SLICE : (baseViewType == X265_TYPE_P) ? P_SLICE : I_SLICE;
>              }
> -            if (m_param->analysisLoad && m_param->bDisableLookahead)
> +            if (strlen(m_param->analysisLoad) && m_param->bDisableLookahead)
>              {
>                  frameEnc[0]->m_dts = frameEnc[0]->m_analysisData.lookahead.dts;
>                  frameEnc[0]->m_reorderedPts = frameEnc[0]->m_analysisData.lookahead.reorderedPts;
> @@ -2409,7 +2394,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
>  
>              curEncoder->m_rce.encodeOrder = frameEnc[0]->m_encodeOrder = m_encodedFrameNum++;
>  
> -            if (!m_param->analysisLoad || !m_param->bDisableLookahead)
> +            if (!strlen(m_param->analysisLoad) || !m_param->bDisableLookahead)
>              {
>                  if (m_bframeDelay)
>                  {
> @@ -2424,7 +2409,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
>              }
>  
>              /* Allocate analysis data before encode in save mode. This is allocated in frameEnc[0] */
> -            if (m_param->analysisSave && !m_param->analysisLoad)
> +            if (strlen(m_param->analysisSave) && !strlen(m_param->analysisLoad))
>              {
>                  x265_analysis_data* analysis = &frameEnc[0]->m_analysisData;
>                  analysis->poc = frameEnc[0]->m_poc;
> @@ -2618,8 +2603,8 @@ int Encoder::reconfigureParam(x265_param* encParam, x265_param* param)
>          encParam->bEnableRectInter = param->bEnableRectInter;
>          encParam->maxNumMergeCand = param->maxNumMergeCand;
>          encParam->bIntraInBFrames = param->bIntraInBFrames;
> -        if (param->scalingLists && !encParam->scalingLists)
> -            encParam->scalingLists = strdup(param->scalingLists);
> +        if (strlen(param->scalingLists) && !strlen(encParam->scalingLists))
> +            snprintf(encParam->scalingLists, X265_MAX_STRING_SIZE, "%s", param->scalingLists);
>  
>          encParam->rc.aqMode = param->rc.aqMode;
>          encParam->rc.aqStrength = param->rc.aqStrength;
> @@ -3442,7 +3427,7 @@ void Encoder::getStreamHeaders(NALList& list, Entropy& sbacCoder, Bitstream& bs)
>              cllsei.writeSEImessages(bs, m_sps, NAL_UNIT_PREFIX_SEI, list, m_param->bSingleSeiNal);
>          }
>  
> -        if (m_param->masteringDisplayColorVolume)
> +        if (strlen(m_param->masteringDisplayColorVolume))
>          {
>              SEIMasteringDisplayColorVolume mdsei;
>              if (mdsei.parse(m_param->masteringDisplayColorVolume))
> @@ -3785,8 +3770,8 @@ void Encoder::configureZone(x265_param *p, x265_param *zone)
>          p->bEnableRectInter = zone->bEnableRectInter;
>          p->maxNumMergeCand = zone->maxNumMergeCand;
>          p->bIntraInBFrames = zone->bIntraInBFrames;
> -        if (zone->scalingLists)
> -            p->scalingLists = strdup(zone->scalingLists);
> +        if (strlen(zone->scalingLists))
> +            snprintf(p->scalingLists, X265_MAX_STRING_SIZE, "%s", zone->scalingLists);
>  
>          p->rc.aqMode = zone->rc.aqMode;
>          p->rc.aqStrength = zone->rc.aqStrength;
> @@ -3883,15 +3868,15 @@ void Encoder::configureVideoSignalTypePreset(x265_param* p)
>              p->bEmitHDR10SEI = 1;
>              if (!strcmp(colorVolume, "P3D65x1000n0005"))
>              {
> -                p->masteringDisplayColorVolume = strdup("G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,5)");
> +                snprintf(p->masteringDisplayColorVolume, X265_MAX_STRING_SIZE, "G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,5)");
>              }
>              else if (!strcmp(colorVolume, "P3D65x4000n005"))
>              {
> -                p->masteringDisplayColorVolume = strdup("G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(40000000,50)");
> +                snprintf(p->masteringDisplayColorVolume, X265_MAX_STRING_SIZE, "G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(40000000,50)");
>              }
>              else if (!strcmp(colorVolume, "BT2100x108n0005"))
>              {
> -                p->masteringDisplayColorVolume = strdup("G(8500,39850)B(6550,2300)R(34000,146000)WP(15635,16450)L(10000000,1)");
> +                snprintf(p->masteringDisplayColorVolume, X265_MAX_STRING_SIZE, "G(8500,39850)B(6550,2300)R(34000,146000)WP(15635,16450)L(10000000,1)");
>              }
>              else
>              {
> @@ -4107,37 +4092,37 @@ void Encoder::configure(x265_param *p)
>          p->rc.rfConstantMin = 0;
>      }
>  
> -    if (p->analysisSaveReuseLevel && !p->analysisSave)
> +    if (p->analysisSaveReuseLevel && !strlen(p->analysisSave))
>      {
>          x265_log(p, X265_LOG_WARNING, "analysis-save-reuse-level can be set only when analysis-save is enabled."
>              " Resetting analysis-save-reuse-level to 0.\n");
>          p->analysisSaveReuseLevel = 0;
>      }
>  
> -    if (p->analysisLoadReuseLevel && !p->analysisLoad)
> +    if (p->analysisLoadReuseLevel && !strlen(p->analysisLoad))
>      {
>          x265_log(p, X265_LOG_WARNING, "analysis-load-reuse-level can be set only when analysis-load is enabled."
>              " Resetting analysis-load-reuse-level to 0.\n");
>          p->analysisLoadReuseLevel = 0;
>      }
>  
> -    if (p->analysisSave && !p->analysisSaveReuseLevel)
> +    if (strlen(p->analysisSave) && !p->analysisSaveReuseLevel)
>          p->analysisSaveReuseLevel = 5;
>  
> -    if (p->analysisLoad && !p->analysisLoadReuseLevel)
> +    if (strlen(p->analysisLoad) && !p->analysisLoadReuseLevel)
>          p->analysisLoadReuseLevel = 5;
>  
> -    if ((p->analysisLoad || p->analysisSave) && (p->bDistributeModeAnalysis || p->bDistributeMotionEstimation))
> +    if ((strlen(p->analysisLoad) || p->analysisSave) && (p->bDistributeModeAnalysis || p->bDistributeMotionEstimation))
>      {
>          x265_log(p, X265_LOG_WARNING, "Analysis load/save options incompatible with pmode/pme, Disabling pmode/pme\n");
>          p->bDistributeMotionEstimation = p->bDistributeModeAnalysis = 0;
>      }
>  
> -    if ((p->analysisLoad || p->analysisSave) && (p->analysisMultiPassRefine || p->analysisMultiPassDistortion))
> +    if ((strlen(p->analysisLoad) || strlen(p->analysisSave)) && (p->analysisMultiPassRefine || p->analysisMultiPassDistortion))
>      {
>          x265_log(p, X265_LOG_WARNING, "Cannot use Analysis load/save option and multi-pass-opt-analysis/multi-pass-opt-distortion together,"
>              "Disabling Analysis load/save and multi-pass-opt-analysis/multi-pass-opt-distortion\n");
> -        p->analysisSave = p->analysisLoad = NULL;
> +        p->analysisSave[0] = p->analysisLoad[0] = 0;
>          p->analysisMultiPassRefine = p->analysisMultiPassDistortion = 0;
>      }
>      if (p->scaleFactor)
> @@ -4190,12 +4175,12 @@ void Encoder::configure(x265_param *p)
>  
>      if (p->ctuDistortionRefine == CTU_DISTORTION_INTERNAL)
>      {
> -        if (!p->analysisLoad && !p->analysisSave)
> +        if (!strlen(p->analysisLoad) && !strlen(p->analysisSave))
>          {
>              x265_log(p, X265_LOG_WARNING, "refine-ctu-distortion 1 requires analysis save/load. Disabling refine-ctu-distortion\n");
>              p->ctuDistortionRefine = 0;
>          }
> -        if (p->scaleFactor && p->analysisLoad)
> +        if (p->scaleFactor && strlen(p->analysisLoad))
>          {
>              x265_log(p, X265_LOG_WARNING, "refine-ctu-distortion 1 cannot be enabled along with multi resolution analysis refinement. Disabling refine-ctu-distortion\n");
>              p->ctuDistortionRefine = 0;
> @@ -4317,7 +4302,7 @@ void Encoder::configure(x265_param *p)
>      p->bEnableTSkipFast &= p->bEnableTransformSkip;
>      p->bLimitSAO &= p->bEnableSAO;
>  
> -    if (m_param->bUseAnalysisFile && m_param->analysisLoad && (p->confWinRightOffset || p->confWinBottomOffset))
> +    if (m_param->bUseAnalysisFile && strlen(m_param->analysisLoad) && (p->confWinRightOffset || p->confWinBottomOffset))
>          x265_log(p, X265_LOG_WARNING, "It is recommended not to set conformance window offset in file based analysis-load."
>                                        " Offsets are shared in the analysis file already.\n");
>      /* initialize the conformance window */
> @@ -4328,7 +4313,7 @@ void Encoder::configure(x265_param *p)
>      m_conformanceWindow.leftOffset = 0;
>  
>      uint32_t padsize = 0;
> -    if (m_param->analysisLoad && m_param->bUseAnalysisFile)
> +    if (strlen(m_param->analysisLoad) && m_param->bUseAnalysisFile)
>      {
>          m_analysisFileIn = x265_fopen(m_param->analysisLoad, "rb");
>          if (!m_analysisFileIn)
> @@ -4459,19 +4444,19 @@ void Encoder::configure(x265_param *p)
>          m_param->bEnableFrameDuplication = 0;
>      }
>  #ifdef ENABLE_HDR10_PLUS
> -    if (m_param->bDhdr10opt && m_param->toneMapFile == NULL)
> +    if (m_param->bDhdr10opt && strlen(m_param->toneMapFile) == 0)
>      {
>          x265_log(p, X265_LOG_WARNING, "Disabling dhdr10-opt. dhdr10-info must be enabled.\n");
>          m_param->bDhdr10opt = 0;
>      }
>  
> -    if (m_param->toneMapFile)
> +    if (strlen(m_param->toneMapFile))
>      {
>          if (!x265_fopen(p->toneMapFile, "r"))
>          {
>              x265_log(p, X265_LOG_ERROR, "Unable to open tone-map file.\n");
>              m_bToneMap = 0;
> -            m_param->toneMapFile = NULL;
> +            m_param->toneMapFile[0] = 0;
>              m_aborted = true;
>          }
>          else
> @@ -4480,11 +4465,11 @@ void Encoder::configure(x265_param *p)
>      else
>          m_bToneMap = 0;
>  #else
> -    if (m_param->toneMapFile)
> +    if (strlen(m_param->toneMapFile))
>      {
>          x265_log(p, X265_LOG_WARNING, "--dhdr10-info disabled. Enable HDR10_PLUS in cmake.\n");
>          m_bToneMap = 0;
> -        m_param->toneMapFile = NULL;
> +        m_param->toneMapFile[0] = 0;
>      }
>      else if (m_param->bDhdr10opt)
>      {
> @@ -4648,10 +4633,10 @@ void Encoder::configure(x265_param *p)
>          }
>      }
>  
> -    if (p->videoSignalTypePreset)     // Default disabled.
> +    if (strlen(p->videoSignalTypePreset))     // Default disabled.
>          configureVideoSignalTypePreset(p);
>  
> -    if (m_param->toneMapFile || p->bHDR10Opt || p->bEmitHDR10SEI)
> +    if (strlen(m_param->toneMapFile) || p->bHDR10Opt || p->bEmitHDR10SEI)
>      {
>          if (!p->bRepeatHeaders)
>          {
> @@ -6281,6 +6266,8 @@ void Encoder::readUserSeiFile(x265_sei_payload& seiMsg, int curPoc)
>              x265_log(m_param, X265_LOG_WARNING, "SEI message for frame %d is not inserted. Will support only PREFIX SEI messages.\n", poc);
>              break;
>          }
> +        if (base64Decode)
> +            free(base64Decode);
>      }
>  }
>  
> diff --git a/source/encoder/encoder.h b/source/encoder/encoder.h
> index 6289779e7..95c73de8a 100644
> --- a/source/encoder/encoder.h
> +++ b/source/encoder/encoder.h
> @@ -209,6 +209,7 @@ public:
>      x265_param*        m_param;
>      x265_param*        m_latestParam;     // Holds latest param during a reconfigure
>      x265_param*        m_zoneParam;
> +    x265_param*        m_templateParam;
>      RateControl*       m_rateControl;
>      Lookahead*         m_lookahead;
>      AdaptiveFrameDuplication* m_dupBuffer[DUP_BUFFER];      // picture buffer of size 2
> diff --git a/source/encoder/frameencoder.cpp b/source/encoder/frameencoder.cpp
> index b6f2d6ed1..95eef813b 100644
> --- a/source/encoder/frameencoder.cpp
> +++ b/source/encoder/frameencoder.cpp
> @@ -109,8 +109,6 @@ void FrameEncoder::destroy()
>  
>      if (m_param->bEnableTemporalFilter)
>      {
> -        delete m_frameEncTF->m_metld;
> -
>          for (int i = 0; i < (m_frameEncTF->m_range << 1); i++)
>              m_frameEncTF->destroyRefPicInfo(&m_mcstfRefList[i]);
>  
> @@ -368,7 +366,7 @@ void FrameEncoder::threadMain()
>              while (!m_frame[0]->m_ctuInfo)
>                  m_frame[0]->m_copied.wait();
>          }
> -        if ((m_param->bAnalysisType == AVC_INFO) && !m_param->analysisSave && !m_param->analysisLoad && !(IS_X265_TYPE_I(m_frame[0]->m_lowres.sliceType)))
> +        if ((m_param->bAnalysisType == AVC_INFO) && !strlen(m_param->analysisSave) && !strlen(m_param->analysisLoad) && !(IS_X265_TYPE_I(m_frame[0]->m_lowres.sliceType)))
>          {
>              while (((m_frame[0]->m_analysisData.interData == NULL && m_frame[0]->m_analysisData.intraData == NULL) || (uint32_t)m_frame[0]->m_poc != m_frame[0]->m_analysisData.poc))
>                  m_frame[0]->m_copyMVType.wait();
> @@ -555,7 +553,7 @@ void FrameEncoder::compressFrame(int layer)
>          m_cuStats.countWeightAnalyze++;
>          ScopedElapsedTime time(m_cuStats.weightAnalyzeTime);
>  #endif
> -        if (m_param->analysisLoad)
> +        if (strlen(m_param->analysisLoad))
>          {
>              for (int list = 0; list < slice->isInterB() + 1; list++) 
>              {
> @@ -580,7 +578,7 @@ void FrameEncoder::compressFrame(int layer)
>      else
>          slice->disableWeights();
>  
> -    if (m_param->analysisSave && (bUseWeightP || bUseWeightB))
> +    if (strlen(m_param->analysisSave) && (bUseWeightP || bUseWeightB))
>          reuseWP = (WeightParam*)m_frame[layer]->m_analysisData.wt;
>      // Generate motion references
>      int numPredDir = slice->isInterP() ? 1 : slice->isInterB() ? 2 : 0;
> @@ -594,7 +592,7 @@ void FrameEncoder::compressFrame(int layer)
>              slice->m_refReconPicList[l][ref] = slice->m_refFrameList[l][ref]->m_reconPic[0];
>              m_mref[l][ref].init(slice->m_refReconPicList[l][ref], w, *m_param);
>          }
> -        if (m_param->analysisSave && (bUseWeightP || bUseWeightB))
> +        if (strlen(m_param->analysisSave) && (bUseWeightP || bUseWeightB))
>          {
>              for (int i = 0; i < (m_param->internalCsp != X265_CSP_I400 ? 3 : 1); i++)
>                  *(reuseWP++) = slice->m_weightPredTable[l][0][i];
> @@ -1656,7 +1654,7 @@ void FrameEncoder::processRowEncoder(int intRow, ThreadLocalData& tld, int layer
>              /* TODO: use defines from slicetype.h for lowres block size */
>              uint32_t block_y = (ctu->m_cuPelY >> m_param->maxLog2CUSize) * noOfBlocks;
>              uint32_t block_x = (ctu->m_cuPelX >> m_param->maxLog2CUSize) * noOfBlocks;
> -            if (!m_param->analysisLoad || !m_param->bDisableLookahead)
> +            if (!strlen(m_param->analysisLoad) || !m_param->bDisableLookahead)
>              {
>                  cuStat.vbvCost = 0;
>                  cuStat.intraVbvCost = 0;
> diff --git a/source/encoder/framefilter.cpp b/source/encoder/framefilter.cpp
> index 71dc42b2c..b58799afd 100644
> --- a/source/encoder/framefilter.cpp
> +++ b/source/encoder/framefilter.cpp
> @@ -162,11 +162,9 @@ void FrameFilter::destroy()
>  
>      if (m_parallelFilter)
>      {
> -        if (m_useSao)
> -        {
> -            for(int row = 0; row < m_numRows; row++)
> -                m_parallelFilter[row].m_sao.destroy((row == 0 ? 1 : 0));
> -        }
> +        // NOTE: don't check m_useSao because it is dynamic controllable
> +        for(int row = 0; row < m_numRows; row++)
> +            m_parallelFilter[row].m_sao.destroy((row == 0 ? 1 : 0));
>  
>          delete[] m_parallelFilter;
>          m_parallelFilter = NULL;
> diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp
> index e46896987..5908992ce 100644
> --- a/source/encoder/ratecontrol.cpp
> +++ b/source/encoder/ratecontrol.cpp
> @@ -496,7 +496,7 @@ bool RateControl::init(const SPS& sps)
>      {
>          /* If the user hasn't defined the stat filename, use the default value */
>          const char *fileName = m_param->rc.statFileName;
> -        if (!fileName)
> +        if (!strlen(fileName))
>              fileName = s_defaultStatFileName;
>          /* Load stat file and init 2pass algo */
>          if (m_param->rc.bStatRead)
> @@ -3329,7 +3329,7 @@ void RateControl::terminate()
>  void RateControl::destroy()
>  {
>      const char *fileName = m_param->rc.statFileName;
> -    if (!fileName)
> +    if (!strlen(fileName))
>          fileName = s_defaultStatFileName;
>  
>      if (m_statFileOut)
> diff --git a/source/encoder/search.cpp b/source/encoder/search.cpp
> index e398843a8..2a324700d 100644
> --- a/source/encoder/search.cpp
> +++ b/source/encoder/search.cpp
> @@ -2135,7 +2135,7 @@ void Search::singleMotionEstimation(Search& master, Mode& interMode, const Predi
>      bool bLowresMVP = false;
>      MV mvmin, mvmax, outmv, mvp = amvp[mvpIdx], mvp_lowres;
>  
> -    if (!m_param->analysisSave && !m_param->analysisLoad) /* Prevents load/save outputs from diverging if lowresMV is not available */
> +    if (!strlen(m_param->analysisSave) && !strlen(m_param->analysisLoad)) /* Prevents load/save outputs from diverging if lowresMV is not available */
>      {
>          MV lmv = getLowresMV(interMode.cu, pu, list, ref);
>          int layer = m_param->numViews > 1 ? m_frame->m_viewId : (m_param->numScalableLayers > 1) ? m_frame->m_sLayerId : 0;
> @@ -2476,7 +2476,7 @@ void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChroma
>                      MV mvmin, mvmax, outmv, mvp = amvp[mvpIdx], mvp_lowres;
>                      bool bLowresMVP = false;
>  
> -                    if (!m_param->analysisSave && !m_param->analysisLoad) /* Prevents load/save outputs from diverging when lowresMV is not available */
> +                    if (!strlen(m_param->analysisSave) && !strlen(m_param->analysisLoad)) /* Prevents load/save outputs from diverging when lowresMV is not available */
>                      {
>                          MV lmv = getLowresMV(cu, pu, list, ref);
>                          int layer = m_param->numViews > 1 ? m_frame->m_viewId : (m_param->numScalableLayers > 1) ? m_frame->m_sLayerId : 0;
> diff --git a/source/encoder/slicetype.cpp b/source/encoder/slicetype.cpp
> index 046cf1596..f44c11ac4 100644
> --- a/source/encoder/slicetype.cpp
> +++ b/source/encoder/slicetype.cpp
> @@ -1194,7 +1194,7 @@ void Lookahead::destroy()
>  /* Called by API thread */
>  void Lookahead::addPicture(Frame& curFrame, int sliceType)
>  {
> -    if (m_param->analysisLoad && m_param->bDisableLookahead)
> +    if (strlen(m_param->analysisLoad) && m_param->bDisableLookahead)
>      {
>          if (!m_filled)
>              m_filled = true;
> @@ -1295,7 +1295,7 @@ Frame* Lookahead::getDecidedPicture()
>              return out;
>          }
>  
> -        if (m_param->analysisLoad && m_param->bDisableLookahead)
> +        if (strlen(m_param->analysisLoad) && m_param->bDisableLookahead)
>              return NULL;
>  
>          findJob(-1); /* run slicetypeDecide() if necessary */
> @@ -1365,14 +1365,14 @@ void Lookahead::getEstimatedPictureCost(Frame *curFrame)
>      default:
>          return;
>      }
> -    if (!curFrame->m_param->analysisLoad || !curFrame->m_param->bDisableLookahead)
> +    if (!strlen(curFrame->m_param->analysisLoad) || !curFrame->m_param->bDisableLookahead)
>      {
>          X265_CHECK(curFrame->m_lowres.costEst[b - p0][p1 - b] > 0, "Slice cost not estimated\n")
>  
>          if (curFrame->m_param->rc.cuTree && !curFrame->m_param->rc.bStatRead)
>              /* update row satds based on cutree offsets */
>              curFrame->m_lowres.satdCost = frameCostRecalculate(frames, p0, p1, b);
> -        else if (!curFrame->m_param->analysisLoad || curFrame->m_param->scaleFactor || curFrame->m_param->bAnalysisType == HEVC_INFO)
> +        else if (!strlen(curFrame->m_param->analysisLoad) || curFrame->m_param->scaleFactor || curFrame->m_param->bAnalysisType == HEVC_INFO)
>          {
>              if (curFrame->m_param->rc.aqMode)
>                  curFrame->m_lowres.satdCost = curFrame->m_lowres.costEstAq[b - p0][p1 - b];
> @@ -1909,7 +1909,7 @@ void Lookahead::slicetypeDecide()
>          if (!m_param->rc.bStatRead)
>              slicetypeAnalyse(frames, false);
>          bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;
> -        if ((m_param->analysisLoad && m_param->scaleFactor && bIsVbv) || m_param->bliveVBV2pass)
> +        if ((strlen(m_param->analysisLoad) && m_param->scaleFactor && bIsVbv) || m_param->bliveVBV2pass)
>          {
>              int numFrames;
>              for (numFrames = 0; numFrames < maxSearch; numFrames++)
> @@ -1923,7 +1923,7 @@ void Lookahead::slicetypeDecide()
>      }
>  
>      int bframes, brefs;
> -    if (!m_param->analysisLoad || m_param->bAnalysisType == HEVC_INFO)
> +    if (!strlen(m_param->analysisLoad) || m_param->bAnalysisType == HEVC_INFO)
>      {
>          bool isClosedGopRadl = m_param->radl && (m_param->keyframeMax != m_param->keyframeMin);
>          for (bframes = 0, brefs = 0;; bframes++)
> @@ -2340,7 +2340,7 @@ void Lookahead::slicetypeDecide()
>              if (!m_param->rc.bStatRead)
>                  slicetypeAnalyse(frames, true);
>              bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;
> -            if ((m_param->analysisLoad && m_param->scaleFactor && bIsVbv) || m_param->bliveVBV2pass)
> +            if ((strlen(m_param->analysisLoad) && m_param->scaleFactor && bIsVbv) || m_param->bliveVBV2pass)
>              {
>                  int numFrames;
>                  for (numFrames = 0; numFrames < maxSearch; numFrames++)
> @@ -2485,7 +2485,7 @@ void Lookahead::slicetypeDecide()
>              if (!m_param->rc.bStatRead)
>                  slicetypeAnalyse(frames, true);
>              bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;
> -            if ((m_param->analysisLoad && m_param->scaleFactor && bIsVbv) || m_param->bliveVBV2pass)
> +            if ((strlen(m_param->analysisLoad) && m_param->scaleFactor && bIsVbv) || m_param->bliveVBV2pass)
>              {
>                  int numFrames;
>                  for (numFrames = 0; numFrames < maxSearch; numFrames++)
> diff --git a/source/x265.cpp b/source/x265.cpp
> index c9d2513e2..f392d27bf 100644
> --- a/source/x265.cpp
> +++ b/source/x265.cpp
> @@ -154,6 +154,9 @@ static bool parseAbrConfig(FILE* abrConfig, CLIOptions cliopt[], uint8_t numEnco
>      char line[1024];
>      char* argLine;
>  
> +    char **argv = (char**)alloca(256 * sizeof(char *));
> +    char *strPool = (char*)alloca(256 * X265_MAX_STRING_SIZE * sizeof(char));
> +    int strPoolSize = 256 * X265_MAX_STRING_SIZE;
>      for (uint32_t i = 0; i < numEncodes; i++)
>      {
>          if (fgets(line, sizeof(line), abrConfig) == NULL) {
> @@ -168,7 +171,6 @@ static bool parseAbrConfig(FILE* abrConfig, CLIOptions cliopt[], uint8_t numEnco
>          char* start = strchr(argLine, ' ');
>          while (isspace((unsigned char)*start)) start++;
>          int argc = 0;
> -        char **argv = (char**)malloc(256 * sizeof(char *));
>          // Adding a dummy string to avoid file parsing error
>          argv[argc++] = (char *)"x265";
>  
> @@ -193,15 +195,18 @@ static bool parseAbrConfig(FILE* abrConfig, CLIOptions cliopt[], uint8_t numEnco
>          }
>          else
>          {
> -            cliopt[i].encName = strdup(head[0]);
> +            snprintf(cliopt[i].encName, X265_MAX_STRING_SIZE, "%s", head[0]);
>              cliopt[i].loadLevel = atoi(head[1]);
> -            cliopt[i].reuseName = strdup(head[2]);
> +            snprintf(cliopt[i].reuseName, X265_MAX_STRING_SIZE, "%s", head[2]);
>          }
>  
>          char* token = strtok(start, " ");
>          while (token)
>          {
> -            argv[argc++] = strdup(token);
> +            argv[argc++] = strPool;
> +            strPool += strlen(token);
> +            strPoolSize -= strlen(token);
> +            strcpy(argv[argc++], token);
>              token = strtok(NULL, " ");
>          }
>          argv[argc] = NULL;
> @@ -213,6 +218,7 @@ static bool parseAbrConfig(FILE* abrConfig, CLIOptions cliopt[], uint8_t numEnco
>              exit(1);
>          }
>      }
> +    X265_CHECK(strPoolSize >= 0, "string pool broken!");
>      return true;
>  }
>  
> @@ -319,11 +325,11 @@ int main(int argc, char **argv)
>              if (abrEnc->m_passEnc[idx]->m_ret)
>              {
>                  if (isAbrLadder)
> -                    x265_log(NULL, X265_LOG_INFO, "Error generating ABR-ladder \n");
> -                ret = abrEnc->m_passEnc[idx]->m_ret;
> -                threadsActive = 0;
> -                break;
> -            }
> +                    x265_log(NULL, X265_LOG_INFO, "Error generating ABR-ladder \n");
> +                ret = abrEnc->m_passEnc[idx]->m_ret;
> +                threadsActive = 0;
> +                break;
> +            }
>          }
>      }
>  
> diff --git a/source/x265.h b/source/x265.h
> index 13c4a47e2..671e196f6 100644
> --- a/source/x265.h
> +++ b/source/x265.h
> @@ -36,6 +36,8 @@ extern "C" {
>  #pragma warning(disable: 4201) // non-standard extension used (nameless struct/union)
>  #endif
>  
> +#define X265_MAX_STRING_SIZE    (256)
> +
>  /* x265_encoder:
>   *      opaque handler for encoder */
>  typedef struct x265_encoder x265_encoder;
> @@ -1141,7 +1143,7 @@ typedef struct x265_param
>       *
>       * Frame encoders are distributed between the available thread pools, and
>       * the encoder will never generate more thread pools than frameNumThreads */
> -    const char* numaPools;
> +    char numaPools[X265_MAX_STRING_SIZE];
>  
>      /* Enable wavefront parallel processing, greatly increases parallelism for
>       * less than 1% compression efficiency loss. Requires a thread pool, enabled
> @@ -1185,7 +1187,7 @@ typedef struct x265_param
>       * per-slice statistics to this log file in encode order. Otherwise the
>       * encoder will emit per-stream statistics into the log file when
>       * x265_encoder_log is called (presumably at the end of the encode) */
> -    const char* csvfn;
> +    char      csvfn[X265_MAX_STRING_SIZE];
>  
>      /*== Internal Picture Specification ==*/
>  
> @@ -1465,7 +1467,7 @@ typedef struct x265_param
>       * - all other strings indicate a filename containing custom scaling lists
>       *   in the HM format. The encode will fail if the file is not parsed
>       *   correctly. Custom lists must be signaled in the SPS. */
> -    const char *scalingLists;
> +    char scalingLists[X265_MAX_STRING_SIZE];
>  
>      /*== Intra Coding Tools ==*/
>  
> @@ -1650,7 +1652,7 @@ typedef struct x265_param
>      int       analysisReuseMode;
>  
>      /* Filename for multi-pass-opt-analysis/distortion. Default name is "x265_analysis.dat" */
> -    const char* analysisReuseFileName;
> +    char      analysisReuseFileName[X265_MAX_STRING_SIZE];
>  
>      /*== Rate Control ==*/
>  
> @@ -1767,7 +1769,7 @@ typedef struct x265_param
>  
>          /* Filename of the 2pass output/input stats file, if unspecified the
>           * encoder will default to using x265_2pass.log */
> -        const char* statFileName;
> +        char statFileName[X265_MAX_STRING_SIZE];
>  
>          /* temporally blur quants */
>          double    qblur;
> @@ -1791,7 +1793,7 @@ typedef struct x265_param
>           * are separated by comma, space or newline. Text after a hash (#) is
>           * ignored. The lambda tables are process-global, so these new lambda
>           * values will affect all encoders in the same process */
> -        const char* lambdaFileName;
> +        char lambdaFileName[X265_MAX_STRING_SIZE];
>  
>          /* Enable stricter conditions to check bitrate deviations in CBR mode. May compromise
>           * quality to maintain bitrate adherence */
> @@ -1828,7 +1830,7 @@ typedef struct x265_param
>          int       dataShareMode;
>  
>          /* Unique shared memory name. Required if the shared memory mode enabled. NULL by default */
> -        const char* sharedMemName;
> +        char sharedMemName[X265_MAX_STRING_SIZE];
>  
>      } rc;
>  
> @@ -1933,7 +1935,7 @@ typedef struct x265_param
>       * are unsigned 16bit integers and %u are unsigned 32bit integers. The SEI
>       * includes X,Y display primaries for RGB channels, white point X,Y and
>       * max,min luminance values. */
> -    const char* masteringDisplayColorVolume;
> +    char masteringDisplayColorVolume[X265_MAX_STRING_SIZE];
>  
>      /* Maximum Content light level(MaxCLL), specified as integer that indicates the
>       * maximum pixel intensity level in units of 1 candela per square metre of the
> @@ -2022,7 +2024,7 @@ typedef struct x265_param
>      int       bLimitSAO;
>  
>      /* File containing the tone mapping information */
> -    const char*     toneMapFile;
> +    char      toneMapFile[X265_MAX_STRING_SIZE];
>  
>      /* Insert tone mapping information only for IDR frames and when the 
>       * tone mapping information changes. */
> @@ -2098,11 +2100,11 @@ typedef struct x265_param
>      int       gopLookahead;
>  
>      /*Write per-frame analysis information into analysis buffers. Default disabled. */
> -    const char* analysisSave;
> +    char analysisSave[X265_MAX_STRING_SIZE];
>  
>      /* Read analysis information into analysis buffer and use this analysis information
>       * to reduce the amount of work the encoder must perform. Default disabled. */
> -    const char* analysisLoad;
> +    char analysisLoad[X265_MAX_STRING_SIZE];
>  
>      /*Number of RADL pictures allowed in front of IDR*/
>      int radl;
> @@ -2134,7 +2136,7 @@ typedef struct x265_param
>      * Default 0 (disabled). */
>      int       chunkEnd;
>      /* File containing base64 encoded SEI messages in POC order */
> -    const char*    naluFile;
> +    char      naluFile[X265_MAX_STRING_SIZE];
>  
>      /* Generate bitstreams confirming to the specified dolby vision profile,
>       * note that 0x7C01 makes RPU appear to be an unspecified NAL type in
> @@ -2295,7 +2297,7 @@ typedef struct x265_param
>      * precedence than individual VUI parameters. If any individual VUI option is specified
>      * together with this, which changes the values set corresponding to the system-id
>      * or color-volume, it will be discarded. */
> -    const char* videoSignalTypePreset;
> +    char     videoSignalTypePreset[X265_MAX_STRING_SIZE];
>  
>      /* Flag indicating whether the encoder should emit an End of Bitstream
>       * NAL at the end of bitstream. Default false */
> diff --git a/source/x265cli.cpp b/source/x265cli.cpp
> index 12df761cc..fd82ebd22 100755
> --- a/source/x265cli.cpp
> +++ b/source/x265cli.cpp
> @@ -555,7 +555,6 @@ namespace X265_NS {
>              showHelp(globalParam);
>          }
>  
> -        globalParam->rc.zones[zonefileCount].zoneParam = api->param_alloc();
>          if (!globalParam->rc.zones[zonefileCount].zoneParam)
>          {
>              x265_log(NULL, X265_LOG_ERROR, "param alloc failed\n");
> @@ -1131,6 +1130,7 @@ namespace X265_NS {
>          }
>  
>          rewind(zoneFile);
> +        char **args = (char**)alloca(256 * sizeof(char *));
>          param->rc.zones = X265_MALLOC(x265_zone, param->rc.zonefileCount);
>          for (int i = 0; i < param->rc.zonefileCount; i++)
>          {
> @@ -1148,7 +1148,6 @@ namespace X265_NS {
>                  start++;
>                  param->rc.zones[i].startFrame = atoi(argLine);
>                  int argCount = 0;
> -                char **args = (char**)malloc(256 * sizeof(char *));
>                  // Adding a dummy string to avoid file parsing error
>                  args[argCount++] = (char *)"x265";
>                  char* token = strtok(start, " ");
> @@ -1354,6 +1353,7 @@ namespace X265_NS {
>          rewind(multiViewConfig);
>          int linenum = 0;
>          int numInput = 0;
> +        char** args = (char**)malloc(256 * sizeof(char*));
>          while (fgets(line, sizeof(line), multiViewConfig))
>          {
>              if (*line == '#' || (strcmp(line, "\r\n") == 0))
> @@ -1365,7 +1365,6 @@ namespace X265_NS {
>              char* start = strchr(argLine, '-');
>              int argCount = 0;
>              char flag[] = "true";
> -            char** args = (char**)malloc(256 * sizeof(char*));
>              //Adding a dummy string to avoid file parsing error
>              args[argCount++] = (char*)"x265";
>              char* token = strtok(start, " ");
> @@ -1467,10 +1466,12 @@ namespace X265_NS {
>              {
>                  if (api)
>                      api->param_free(param);
> +                free(args);
>                  exit(1);
>              }
>              linenum++;
>          }
> +        free(args);
>          if (numInput != (param->format ? 1 : param->numViews))
>          {
>              x265_log(NULL, X265_LOG_WARNING, "Number of Input files does not match with the given format <%d>\n", param->format);
> diff --git a/source/x265cli.h b/source/x265cli.h
> index 3df0fa7a6..aaa385cb4 100644
> --- a/source/x265cli.h
> +++ b/source/x265cli.h
> @@ -434,8 +434,8 @@ static const struct option long_options[] =
>          /* ABR ladder settings */
>          bool isAbrLadderConfig;
>          bool enableScaler;
> -        char*    encName;
> -        char*    reuseName;
> +        char     encName[X265_MAX_STRING_SIZE];
> +        char     reuseName[X265_MAX_STRING_SIZE];
>          uint32_t encId;
>          int      refId;
>          uint32_t loadLevel;
> @@ -471,8 +471,8 @@ static const struct option long_options[] =
>              bDither = false;
>              isAbrLadderConfig = false;
>              enableScaler = false;
> -            encName = NULL;
> -            reuseName = NULL;
> +            encName[0] = 0;
> +            reuseName[0] = 0;
>              encId = 0;
>              refId = -1;
>              loadLevel = 0;
> -- 
> 2.41.0.windows.1
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
> 
> 
> *Attachments:*
>  • 0002-Memory-Leak-Fix-Part2.patch

-- 
Jean-Baptiste Kempf -  President
+33 672 704 734
https://jbkempf.com/

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20241110/0e049d0d/attachment-0001.htm>


More information about the x265-devel mailing list