/*! * \copy * Copyright (c) 2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <string.h>#include <assert.h>#include <signal.h>#include <stdarg.h>#if defined (ANDROID_NDK)#include <android/log.h>#endif#ifdef ONLY_ENC_FRAMES_NUM#undef ONLY_ENC_FRAMES_NUM#endif//ONLY_ENC_FRAMES_NUM#define ONLY_ENC_FRAMES_NUM INT_MAX // 2, INT_MAX // type the num you try to encode here, 2, 10, etc #if defined (WINDOWS_PHONE)float g_fFPS = 0.0;double g_dEncoderTime = 0.0;int g_iEncodedFrame = 0;#endif #if defined (ANDROID_NDK)#define LOG_TAG "welsenc"#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)#define printf(...) LOGI(__VA_ARGS__)#define fprintf(a, ...) LOGI(__VA_ARGS__)#endif//#define STICK_STREAM_SIZE #include "measure_time.h"#include "read_config.h" #include "typedefs.h" #ifdef _MSC_VER#include <io.h> /* _setmode() */#include <fcntl.h> /* _O_BINARY */#endif//_MSC_VER #include "codec_def.h"#include "codec_api.h"#include "extern.h"#include "macros.h"#include "wels_const.h" #include "mt_defs.h"#include "WelsThreadLib.h" #ifdef _WIN32#ifdef WINAPI_FAMILY#include <winapifamily.h>#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)#define HAVE_PROCESS_AFFINITY#endif#else /* defined(WINAPI_FAMILY) */#define HAVE_PROCESS_AFFINITY#endif#endif /* _WIN32 */ #if defined(__linux__) || defined(__unix__)#define _FILE_OFFSET_BITS 64#endif #include <iostream>using namespace std;using namespace WelsEnc; /* * Layer Context */typedef struct LayerpEncCtx_s { int32_t iDLayerQp; SSliceArgument sSliceArgument;} SLayerPEncCtx; typedef struct tagFilesSet { string strBsFile; string strSeqFile; // for cmd lines string strLayerCfgFile[MAX_DEPENDENCY_LAYER]; char sRecFileName[MAX_DEPENDENCY_LAYER][MAX_FNAME_LEN]; uint32_t uiFrameToBeCoded; bool bEnableMultiBsFile; tagFilesSet() { uiFrameToBeCoded = 0; bEnableMultiBsFile = false; for (int i = 0; i < MAX_DEPENDENCY_LAYER; i++) sRecFileName[i][0] = '\0'; }} SFilesSet; /* Ctrl-C handler */static int g_iCtrlC = 0;static void SigIntHandler (int a) { g_iCtrlC = 1;}static int g_LevelSetting = WELS_LOG_ERROR; int ParseLayerConfig (CReadConfig& cRdLayerCfg, const int iLayer, SEncParamExt& pSvcParam, SFilesSet& sFileSet) { if (!cRdLayerCfg.ExistFile()) { fprintf (stderr, "Unabled to open layer #%d configuration file: %s.\n", iLayer, cRdLayerCfg.GetFileName().c_str()); return 1; } SSpatialLayerConfig* pDLayer = &pSvcParam.sSpatialLayers[iLayer]; int iLeftTargetBitrate = (pSvcParam.iRCMode != RC_OFF_MODE) ? pSvcParam.iTargetBitrate : 0; SLayerPEncCtx sLayerCtx; memset (&sLayerCtx, 0, sizeof (SLayerPEncCtx)); string strTag[4]; string str_ ("SlicesAssign"); const int kiSize = (int)str_.size(); while (!cRdLayerCfg.EndOfFile()) { long iLayerRd = cRdLayerCfg.ReadLine (&strTag[0]); if (iLayerRd > 0) { if (strTag[0].empty()) continue; if (strTag[0].compare ("FrameWidth") == 0) { pDLayer->iVideoWidth = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("FrameHeight") == 0) { pDLayer->iVideoHeight = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("FrameRateOut") == 0) { pDLayer->fFrameRate = (float)atof (strTag[1].c_str()); } else if (strTag[0].compare ("ReconFile") == 0) { const unsigned int kiLen = (unsigned int)strTag[1].length(); if (kiLen >= sizeof (sFileSet.sRecFileName[iLayer])) return -1; sFileSet.sRecFileName[iLayer][kiLen] = '\0'; strncpy (sFileSet.sRecFileName[iLayer], strTag[1].c_str(), kiLen); // confirmed_safe_unsafe_usage } else if (strTag[0].compare ("ProfileIdc") == 0) { pDLayer->uiProfileIdc = (EProfileIdc)atoi (strTag[1].c_str()); } else if (strTag[0].compare ("FRExt") == 0) {// pDLayer->frext_mode = (bool)atoi(strTag[1].c_str()); } else if (strTag[0].compare ("SpatialBitrate") == 0) { pDLayer->iSpatialBitrate = 1000 * atoi (strTag[1].c_str()); if (pSvcParam.iRCMode != RC_OFF_MODE) { if (pDLayer->iSpatialBitrate <= 0) { fprintf (stderr, "Invalid spatial bitrate(%d) in dependency layer #%d.\n", pDLayer->iSpatialBitrate, iLayer); return -1; } if (pDLayer->iSpatialBitrate > iLeftTargetBitrate) { fprintf (stderr, "Invalid spatial(#%d) bitrate(%d) setting due to unavailable left(%d)!\n", iLayer, pDLayer->iSpatialBitrate, iLeftTargetBitrate); return -1; } iLeftTargetBitrate -= pDLayer->iSpatialBitrate; } } else if (strTag[0].compare ("MaxSpatialBitrate") == 0) { pDLayer->iMaxSpatialBitrate = 1000 * atoi (strTag[1].c_str()); if (pSvcParam.iRCMode != RC_OFF_MODE) { if (pDLayer->iMaxSpatialBitrate < 0) { fprintf (stderr, "Invalid max spatial bitrate(%d) in dependency layer #%d.\n", pDLayer->iMaxSpatialBitrate, iLayer); return -1; } if (pDLayer->iMaxSpatialBitrate > 0 && pDLayer->iMaxSpatialBitrate < pDLayer->iSpatialBitrate) { fprintf (stderr, "Invalid max spatial(#%d) bitrate(%d) setting::: < layerBitrate(%d)!\n", iLayer, pDLayer->iMaxSpatialBitrate, pDLayer->iSpatialBitrate); return -1; } } } else if (strTag[0].compare ("InitialQP") == 0) { sLayerCtx.iDLayerQp = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("SliceMode") == 0) { sLayerCtx.sSliceArgument.uiSliceMode = (SliceModeEnum)atoi (strTag[1].c_str()); } else if (strTag[0].compare ("SliceSize") == 0) { //SM_SIZELIMITED_SLICE sLayerCtx.sSliceArgument.uiSliceSizeConstraint = atoi (strTag[1].c_str()); continue; } else if (strTag[0].compare ("SliceNum") == 0) { sLayerCtx.sSliceArgument.uiSliceNum = atoi (strTag[1].c_str()); } else if (strTag[0].compare (0, kiSize, str_) == 0) { const char* kpString = strTag[0].c_str(); int uiSliceIdx = atoi (&kpString[kiSize]); assert (uiSliceIdx < MAX_SLICES_NUM); sLayerCtx.sSliceArgument.uiSliceMbNum[uiSliceIdx] = atoi (strTag[1].c_str()); } } } pDLayer->iDLayerQp = sLayerCtx.iDLayerQp; pDLayer->sSliceArgument.uiSliceMode = sLayerCtx.sSliceArgument.uiSliceMode; memcpy (&pDLayer->sSliceArgument, &sLayerCtx.sSliceArgument, sizeof (SSliceArgument)); // confirmed_safe_unsafe_usage memcpy (&pDLayer->sSliceArgument.uiSliceMbNum[0], &sLayerCtx.sSliceArgument.uiSliceMbNum[0], sizeof (sLayerCtx.sSliceArgument.uiSliceMbNum)); // confirmed_safe_unsafe_usage return 0;}int ParseConfig (CReadConfig& cRdCfg, SSourcePicture* pSrcPic, SEncParamExt& pSvcParam, SFilesSet& sFileSet) { string strTag[4]; int32_t iRet = 0; int8_t iLayerCount = 0; while (!cRdCfg.EndOfFile()) { long iRd = cRdCfg.ReadLine (&strTag[0]); if (iRd > 0) { if (strTag[0].empty()) continue; if (strTag[0].compare ("UsageType") == 0) { pSvcParam.iUsageType = (EUsageType)atoi (strTag[1].c_str()); } else if (strTag[0].compare ("SimulcastAVC") == 0) { pSvcParam.bSimulcastAVC = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("SourceWidth") == 0) { pSrcPic->iPicWidth = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("SourceHeight") == 0) { pSrcPic->iPicHeight = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("InputFile") == 0) { if (strTag[1].length() > 0) sFileSet.strSeqFile = strTag[1]; } else if (strTag[0].compare ("OutputFile") == 0) { sFileSet.strBsFile = strTag[1]; } else if (strTag[0].compare ("MaxFrameRate") == 0) { pSvcParam.fMaxFrameRate = (float)atof (strTag[1].c_str()); } else if (strTag[0].compare ("FramesToBeEncoded") == 0) { sFileSet.uiFrameToBeCoded = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("TemporalLayerNum") == 0) { pSvcParam.iTemporalLayerNum = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("IntraPeriod") == 0) { pSvcParam.uiIntraPeriod = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("MaxNalSize") == 0) { pSvcParam.uiMaxNalSize = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("SpsPpsIDStrategy") == 0) { int32_t iValue = atoi (strTag[1].c_str()); switch (iValue) { case 0: pSvcParam.eSpsPpsIdStrategy = CONSTANT_ID; break; case 0x01: pSvcParam.eSpsPpsIdStrategy = INCREASING_ID; break; case 0x02: pSvcParam.eSpsPpsIdStrategy = SPS_LISTING; break; case 0x03: pSvcParam.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING; break; case 0x06: pSvcParam.eSpsPpsIdStrategy = SPS_PPS_LISTING; break; default: pSvcParam.eSpsPpsIdStrategy = CONSTANT_ID; break; } } else if (strTag[0].compare ("EnableMultiBsFile") == 0) { sFileSet.bEnableMultiBsFile = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableScalableSEI") == 0) { pSvcParam.bEnableSSEI = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableFrameCropping") == 0) { pSvcParam.bEnableFrameCroppingFlag = (atoi (strTag[1].c_str()) != 0); } else if (strTag[0].compare ("EntropyCodingModeFlag") == 0) { pSvcParam.iEntropyCodingModeFlag = (atoi (strTag[1].c_str()) != 0); } else if (strTag[0].compare ("ComplexityMode") == 0) { pSvcParam.iComplexityMode = (ECOMPLEXITY_MODE) (atoi (strTag[1].c_str())); } else if (strTag[0].compare ("LoopFilterDisableIDC") == 0) { pSvcParam.iLoopFilterDisableIdc = (int8_t)atoi (strTag[1].c_str()); if (pSvcParam.iLoopFilterDisableIdc > 6 || pSvcParam.iLoopFilterDisableIdc < 0) { fprintf (stderr, "Invalid parameter in iLoopFilterDisableIdc: %d.\n", pSvcParam.iLoopFilterDisableIdc); iRet = 1; break; } } else if (strTag[0].compare ("LoopFilterAlphaC0Offset") == 0) { pSvcParam.iLoopFilterAlphaC0Offset = (int8_t)atoi (strTag[1].c_str()); if (pSvcParam.iLoopFilterAlphaC0Offset < -6) pSvcParam.iLoopFilterAlphaC0Offset = -6; else if (pSvcParam.iLoopFilterAlphaC0Offset > 6) pSvcParam.iLoopFilterAlphaC0Offset = 6; } else if (strTag[0].compare ("LoopFilterBetaOffset") == 0) { pSvcParam.iLoopFilterBetaOffset = (int8_t)atoi (strTag[1].c_str()); if (pSvcParam.iLoopFilterBetaOffset < -6) pSvcParam.iLoopFilterBetaOffset = -6; else if (pSvcParam.iLoopFilterBetaOffset > 6) pSvcParam.iLoopFilterBetaOffset = 6; } else if (strTag[0].compare ("MultipleThreadIdc") == 0) { // # 0: auto(dynamic imp. internal encoder); 1: multiple threads imp. disabled; > 1: count number of threads; pSvcParam.iMultipleThreadIdc = atoi (strTag[1].c_str()); if (pSvcParam.iMultipleThreadIdc < 0) pSvcParam.iMultipleThreadIdc = 0; else if (pSvcParam.iMultipleThreadIdc > MAX_THREADS_NUM) pSvcParam.iMultipleThreadIdc = MAX_THREADS_NUM; } else if (strTag[0].compare ("UseLoadBalancing") == 0) { pSvcParam.bUseLoadBalancing = (atoi (strTag[1].c_str())) ? true : false; } else if (strTag[0].compare ("RCMode") == 0) { pSvcParam.iRCMode = (RC_MODES) atoi (strTag[1].c_str()); } else if (strTag[0].compare ("TargetBitrate") == 0) { pSvcParam.iTargetBitrate = 1000 * atoi (strTag[1].c_str()); if ((pSvcParam.iRCMode != RC_OFF_MODE) && pSvcParam.iTargetBitrate <= 0) { fprintf (stderr, "Invalid target bitrate setting due to RC enabled. Check TargetBitrate field please!\n"); return 1; } } else if (strTag[0].compare ("MaxOverallBitrate") == 0) { pSvcParam.iMaxBitrate = 1000 * atoi (strTag[1].c_str()); if ((pSvcParam.iRCMode != RC_OFF_MODE) && pSvcParam.iMaxBitrate < 0) { fprintf (stderr, "Invalid max overall bitrate setting due to RC enabled. Check MaxOverallBitrate field please!\n"); return 1; } } else if (strTag[0].compare ("MaxQp") == 0) { pSvcParam.iMaxQp = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("MinQp") == 0) { pSvcParam.iMinQp = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("EnableDenoise") == 0) { pSvcParam.bEnableDenoise = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableSceneChangeDetection") == 0) { pSvcParam.bEnableSceneChangeDetect = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableBackgroundDetection") == 0) { pSvcParam.bEnableBackgroundDetection = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableAdaptiveQuantization") == 0) { pSvcParam.bEnableAdaptiveQuant = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableFrameSkip") == 0) { pSvcParam.bEnableFrameSkip = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableLongTermReference") == 0) { pSvcParam.bEnableLongTermReference = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("LongTermReferenceNumber") == 0) { pSvcParam.iLTRRefNum = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("LtrMarkPeriod") == 0) { pSvcParam.iLtrMarkPeriod = (uint32_t)atoi (strTag[1].c_str()); } else if (strTag[0].compare ("LosslessLink") == 0) { pSvcParam.bIsLosslessLink = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("NumLayers") == 0) { pSvcParam.iSpatialLayerNum = (int8_t)atoi (strTag[1].c_str()); if (pSvcParam.iSpatialLayerNum > MAX_DEPENDENCY_LAYER || pSvcParam.iSpatialLayerNum <= 0) { fprintf (stderr, "Invalid parameter in iSpatialLayerNum: %d.\n", pSvcParam.iSpatialLayerNum); iRet = 1; break; } } else if (strTag[0].compare ("LayerCfg") == 0) { if (strTag[1].length() > 0) sFileSet.strLayerCfgFile[iLayerCount] = strTag[1];// pSvcParam.sDependencyLayers[iLayerCount].uiDependencyId = iLayerCount; ++ iLayerCount; } else if (strTag[0].compare ("PrefixNALAddingCtrl") == 0) { int ctrl_flag = atoi (strTag[1].c_str()); if (ctrl_flag > 1) ctrl_flag = 1; else if (ctrl_flag < 0) ctrl_flag = 0; pSvcParam.bPrefixNalAddingCtrl = ctrl_flag ? true : false; } } } const int8_t kiActualLayerNum = WELS_MIN (pSvcParam.iSpatialLayerNum, iLayerCount); if (pSvcParam.iSpatialLayerNum > kiActualLayerNum) { // fixed number of dependency layer due to parameter error in settings pSvcParam.iSpatialLayerNum = kiActualLayerNum; } assert (kiActualLayerNum <= MAX_DEPENDENCY_LAYER); for (int8_t iLayer = 0; iLayer < kiActualLayerNum; ++ iLayer) { CReadConfig cRdLayerCfg (sFileSet.strLayerCfgFile[iLayer]); if (-1 == ParseLayerConfig (cRdLayerCfg, iLayer, pSvcParam, sFileSet)) { iRet = 1; break; } } return iRet;} void PrintHelp() { printf ("\n Wels SVC Encoder Usage:\n\n"); printf (" Syntax: welsenc.exe -h\n"); printf (" Syntax: welsenc.exe welsenc.cfg\n"); printf (" Syntax: welsenc.exe welsenc.cfg [options]\n"); printf ("\n Supported Options:\n"); printf (" -bf Bit Stream File\n"); printf (" -org Original file, example: -org src.yuv\n"); printf (" -sw the source width\n"); printf (" -sh the source height\n"); printf (" -utype usage type\n"); printf (" -savc simulcast avc\n"); printf (" -frms Number of total frames to be encoded\n"); printf (" -frin input frame rate\n"); printf (" -numtl Temporal layer number (default: 1)\n"); printf (" -iper Intra period (default: -1) : must be a power of 2 of GOP size (or -1)\n"); printf (" -nalsize the Maximum NAL size. which should be larger than the each layer slicesize when slice mode equals to SM_SIZELIMITED_SLICE\n"); printf (" -spsid SPS/PPS id strategy: 0:const, 1: increase, 2: sps list, 3: sps list and pps increase, 4: sps/pps list\n"); printf (" -cabac Entropy coding mode(0:cavlc 1:cabac \n"); printf (" -complexity Complexity mode (default: 0),0: low complexity, 1: medium complexity, 2: high complexity\n"); printf (" -denois Control denoising (default: 0)\n"); printf (" -scene Control scene change detection (default: 0)\n"); printf (" -bgd Control background detection (default: 0)\n"); printf (" -aq Control adaptive quantization (default: 0)\n"); printf (" -ltr Control long term reference (default: 0)\n"); printf (" -ltrnum Control the number of long term reference((1-4):screen LTR,(1-2):video LTR \n"); printf (" -ltrper Control the long term reference marking period \n"); printf (" -threadIdc 0: auto(dynamic imp. internal encoder); 1: multiple threads imp. disabled; > 1: count number of threads \n"); printf (" -loadbalancing 0: turn off loadbalancing between slices when multi-threading available; 1: (default value) turn on loadbalancing between slices when multi-threading available\n"); printf (" -deblockIdc Loop filter idc (0: on, 1: off, \n"); printf (" -alphaOffset AlphaOffset(-6..+6): valid range \n"); printf (" -betaOffset BetaOffset (-6..+6): valid range\n"); printf (" -rc rate control mode: -1-rc off; 0-quality mode; 1-bitrate mode; 2: buffer based mode,can't control bitrate; 3: bitrate mode based on timestamp input;\n"); printf (" -tarb Overall target bitrate\n"); printf (" -maxbrTotal Overall max bitrate\n"); printf (" -maxqp Maximum Qp (default: %d, or for screen content usage: %d)\n", QP_MAX_VALUE, MAX_SCREEN_QP); printf (" -minqp Minimum Qp (default: %d, or for screen content usage: %d)\n", QP_MIN_VALUE, MIN_SCREEN_QP); printf (" -numl Number Of Layers: Must exist with layer_cfg file and the number of input layer_cfg file must equal to the value set by this command\n"); printf (" The options below are layer-based: (need to be set with layer id)\n"); printf (" -lconfig (Layer) (spatial layer configure file)\n"); printf (" -drec (Layer) (reconstruction file);example: -drec 0 rec.yuv. Setting the reconstruction file, this will only functioning when dumping reconstruction is enabled\n"); printf (" -dprofile (Layer) (layer profile);example: -dprofile 0 66. Setting the layer profile, this should be the same for all layers\n"); printf (" -dw (Layer) (output width)\n"); printf (" -dh (Layer) (output height)\n"); printf (" -frout (Layer) (output frame rate)\n"); printf (" -lqp (Layer) (base quality layer qp : must work with -ldeltaqp or -lqparr)\n"); printf (" -ltarb (Layer) (spatial layer target bitrate)\n"); printf (" -lmaxb (Layer) (spatial layer max bitrate)\n"); printf (" -slcmd (Layer) (spatial layer slice mode): pls refer to layerX.cfg for details ( -slcnum: set target slice num; -slcsize: set target slice size constraint ; -slcmbnum: set the first slice mb num under some slice modes) \n"); printf (" -trace (Level)\n"); printf ("\n");} int ParseCommandLine (int argc, char** argv, SSourcePicture* pSrcPic, SEncParamExt& pSvcParam, SFilesSet& sFileSet) { char* pCommand = NULL; SLayerPEncCtx sLayerCtx[MAX_SPATIAL_LAYER_NUM]; int n = 0; string str_ ("SlicesAssign"); while (n < argc) { pCommand = argv[n++]; if (!strcmp (pCommand, "-bf") && (n < argc)) sFileSet.strBsFile.assign (argv[n++]); else if (!strcmp (pCommand, "-utype") && (n < argc)) pSvcParam.iUsageType = (EUsageType)atoi (argv[n++]); else if (!strcmp (pCommand, "-savc") && (n < argc)) pSvcParam.bSimulcastAVC = atoi (argv[n++]) ? true : false; else if (!strcmp (pCommand, "-org") && (n < argc)) sFileSet.strSeqFile.assign (argv[n++]); else if (!strcmp (pCommand, "-sw") && (n < argc))//source width pSrcPic->iPicWidth = atoi (argv[n++]); else if (!strcmp (pCommand, "-sh") && (n < argc))//source height pSrcPic->iPicHeight = atoi (argv[n++]); else if (!strcmp (pCommand, "-frms") && (n < argc)) sFileSet.uiFrameToBeCoded = atoi (argv[n++]); else if (!strcmp (pCommand, "-frin") && (n < argc)) pSvcParam.fMaxFrameRate = (float) atof (argv[n++]); else if (!strcmp (pCommand, "-numtl") && (n < argc)) pSvcParam.iTemporalLayerNum = atoi (argv[n++]); else if (!strcmp (pCommand, "-mfile") && (n < argc)) sFileSet.bEnableMultiBsFile = atoi (argv[n++]) ? true : false; else if (!strcmp (pCommand, "-iper") && (n < argc)) pSvcParam.uiIntraPeriod = atoi (argv[n++]); else if (!strcmp (pCommand, "-nalsize") && (n < argc)) pSvcParam.uiMaxNalSize = atoi (argv[n++]); else if (!strcmp (pCommand, "-spsid") && (n < argc)) { int32_t iValue = atoi (argv[n++]); switch (iValue) { case 0: pSvcParam.eSpsPpsIdStrategy = CONSTANT_ID; break; case 0x01: pSvcParam.eSpsPpsIdStrategy = INCREASING_ID; break; case 0x02:Lines 1–500 of 1161. Load more
/*! * \copy * Copyright (c) 2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <assert.h> #include <signal.h> #include <stdarg.h> #if defined (ANDROID_NDK) #include <android/log.h> #endif #ifdef ONLY_ENC_FRAMES_NUM #undef ONLY_ENC_FRAMES_NUM #endif//ONLY_ENC_FRAMES_NUM #define ONLY_ENC_FRAMES_NUM INT_MAX // 2, INT_MAX // type the num you try to encode here, 2, 10, etc #if defined (WINDOWS_PHONE) float g_fFPS = 0.0; double g_dEncoderTime = 0.0; int g_iEncodedFrame = 0; #endif #if defined (ANDROID_NDK) #define LOG_TAG "welsenc" #define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define printf(...) LOGI(__VA_ARGS__) #define fprintf(a, ...) LOGI(__VA_ARGS__) #endif //#define STICK_STREAM_SIZE #include "measure_time.h" #include "read_config.h" #include "typedefs.h" #ifdef _MSC_VER #include <io.h> /* _setmode() */ #include <fcntl.h> /* _O_BINARY */ #endif//_MSC_VER #include "codec_def.h" #include "codec_api.h" #include "extern.h" #include "macros.h" #include "wels_const.h" #include "mt_defs.h" #include "WelsThreadLib.h" #ifdef _WIN32 #ifdef WINAPI_FAMILY #include <winapifamily.h> #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #define HAVE_PROCESS_AFFINITY #endif #else /* defined(WINAPI_FAMILY) */ #define HAVE_PROCESS_AFFINITY #endif #endif /* _WIN32 */ #if defined(__linux__) || defined(__unix__) #define _FILE_OFFSET_BITS 64 #endif #include <iostream> using namespace std; using namespace WelsEnc; /* * Layer Context */ typedef struct LayerpEncCtx_s { int32_t iDLayerQp; SSliceArgument sSliceArgument; } SLayerPEncCtx; typedef struct tagFilesSet { string strBsFile; string strSeqFile; // for cmd lines string strLayerCfgFile[MAX_DEPENDENCY_LAYER]; char sRecFileName[MAX_DEPENDENCY_LAYER][MAX_FNAME_LEN]; uint32_t uiFrameToBeCoded; bool bEnableMultiBsFile; tagFilesSet() { uiFrameToBeCoded = 0; bEnableMultiBsFile = false; for (int i = 0; i < MAX_DEPENDENCY_LAYER; i++) sRecFileName[i][0] = '\0'; } } SFilesSet; /* Ctrl-C handler */ static int g_iCtrlC = 0; static void SigIntHandler (int a) { g_iCtrlC = 1; } static int g_LevelSetting = WELS_LOG_ERROR; int ParseLayerConfig (CReadConfig& cRdLayerCfg, const int iLayer, SEncParamExt& pSvcParam, SFilesSet& sFileSet) { if (!cRdLayerCfg.ExistFile()) { fprintf (stderr, "Unabled to open layer #%d configuration file: %s.\n", iLayer, cRdLayerCfg.GetFileName().c_str()); return 1; } SSpatialLayerConfig* pDLayer = &pSvcParam.sSpatialLayers[iLayer]; int iLeftTargetBitrate = (pSvcParam.iRCMode != RC_OFF_MODE) ? pSvcParam.iTargetBitrate : 0; SLayerPEncCtx sLayerCtx; memset (&sLayerCtx, 0, sizeof (SLayerPEncCtx)); string strTag[4]; string str_ ("SlicesAssign"); const int kiSize = (int)str_.size(); while (!cRdLayerCfg.EndOfFile()) { long iLayerRd = cRdLayerCfg.ReadLine (&strTag[0]); if (iLayerRd > 0) { if (strTag[0].empty()) continue; if (strTag[0].compare ("FrameWidth") == 0) { pDLayer->iVideoWidth = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("FrameHeight") == 0) { pDLayer->iVideoHeight = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("FrameRateOut") == 0) { pDLayer->fFrameRate = (float)atof (strTag[1].c_str()); } else if (strTag[0].compare ("ReconFile") == 0) { const unsigned int kiLen = (unsigned int)strTag[1].length(); if (kiLen >= sizeof (sFileSet.sRecFileName[iLayer])) return -1; sFileSet.sRecFileName[iLayer][kiLen] = '\0'; strncpy (sFileSet.sRecFileName[iLayer], strTag[1].c_str(), kiLen); // confirmed_safe_unsafe_usage } else if (strTag[0].compare ("ProfileIdc") == 0) { pDLayer->uiProfileIdc = (EProfileIdc)atoi (strTag[1].c_str()); } else if (strTag[0].compare ("FRExt") == 0) { // pDLayer->frext_mode = (bool)atoi(strTag[1].c_str()); } else if (strTag[0].compare ("SpatialBitrate") == 0) { pDLayer->iSpatialBitrate = 1000 * atoi (strTag[1].c_str()); if (pSvcParam.iRCMode != RC_OFF_MODE) { if (pDLayer->iSpatialBitrate <= 0) { fprintf (stderr, "Invalid spatial bitrate(%d) in dependency layer #%d.\n", pDLayer->iSpatialBitrate, iLayer); return -1; } if (pDLayer->iSpatialBitrate > iLeftTargetBitrate) { fprintf (stderr, "Invalid spatial(#%d) bitrate(%d) setting due to unavailable left(%d)!\n", iLayer, pDLayer->iSpatialBitrate, iLeftTargetBitrate); return -1; } iLeftTargetBitrate -= pDLayer->iSpatialBitrate; } } else if (strTag[0].compare ("MaxSpatialBitrate") == 0) { pDLayer->iMaxSpatialBitrate = 1000 * atoi (strTag[1].c_str()); if (pSvcParam.iRCMode != RC_OFF_MODE) { if (pDLayer->iMaxSpatialBitrate < 0) { fprintf (stderr, "Invalid max spatial bitrate(%d) in dependency layer #%d.\n", pDLayer->iMaxSpatialBitrate, iLayer); return -1; } if (pDLayer->iMaxSpatialBitrate > 0 && pDLayer->iMaxSpatialBitrate < pDLayer->iSpatialBitrate) { fprintf (stderr, "Invalid max spatial(#%d) bitrate(%d) setting::: < layerBitrate(%d)!\n", iLayer, pDLayer->iMaxSpatialBitrate, pDLayer->iSpatialBitrate); return -1; } } } else if (strTag[0].compare ("InitialQP") == 0) { sLayerCtx.iDLayerQp = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("SliceMode") == 0) { sLayerCtx.sSliceArgument.uiSliceMode = (SliceModeEnum)atoi (strTag[1].c_str()); } else if (strTag[0].compare ("SliceSize") == 0) { //SM_SIZELIMITED_SLICE sLayerCtx.sSliceArgument.uiSliceSizeConstraint = atoi (strTag[1].c_str()); continue; } else if (strTag[0].compare ("SliceNum") == 0) { sLayerCtx.sSliceArgument.uiSliceNum = atoi (strTag[1].c_str()); } else if (strTag[0].compare (0, kiSize, str_) == 0) { const char* kpString = strTag[0].c_str(); int uiSliceIdx = atoi (&kpString[kiSize]); assert (uiSliceIdx < MAX_SLICES_NUM); sLayerCtx.sSliceArgument.uiSliceMbNum[uiSliceIdx] = atoi (strTag[1].c_str()); } } } pDLayer->iDLayerQp = sLayerCtx.iDLayerQp; pDLayer->sSliceArgument.uiSliceMode = sLayerCtx.sSliceArgument.uiSliceMode; memcpy (&pDLayer->sSliceArgument, &sLayerCtx.sSliceArgument, sizeof (SSliceArgument)); // confirmed_safe_unsafe_usage memcpy (&pDLayer->sSliceArgument.uiSliceMbNum[0], &sLayerCtx.sSliceArgument.uiSliceMbNum[0], sizeof (sLayerCtx.sSliceArgument.uiSliceMbNum)); // confirmed_safe_unsafe_usage return 0; } int ParseConfig (CReadConfig& cRdCfg, SSourcePicture* pSrcPic, SEncParamExt& pSvcParam, SFilesSet& sFileSet) { string strTag[4]; int32_t iRet = 0; int8_t iLayerCount = 0; while (!cRdCfg.EndOfFile()) { long iRd = cRdCfg.ReadLine (&strTag[0]); if (iRd > 0) { if (strTag[0].empty()) continue; if (strTag[0].compare ("UsageType") == 0) { pSvcParam.iUsageType = (EUsageType)atoi (strTag[1].c_str()); } else if (strTag[0].compare ("SimulcastAVC") == 0) { pSvcParam.bSimulcastAVC = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("SourceWidth") == 0) { pSrcPic->iPicWidth = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("SourceHeight") == 0) { pSrcPic->iPicHeight = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("InputFile") == 0) { if (strTag[1].length() > 0) sFileSet.strSeqFile = strTag[1]; } else if (strTag[0].compare ("OutputFile") == 0) { sFileSet.strBsFile = strTag[1]; } else if (strTag[0].compare ("MaxFrameRate") == 0) { pSvcParam.fMaxFrameRate = (float)atof (strTag[1].c_str()); } else if (strTag[0].compare ("FramesToBeEncoded") == 0) { sFileSet.uiFrameToBeCoded = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("TemporalLayerNum") == 0) { pSvcParam.iTemporalLayerNum = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("IntraPeriod") == 0) { pSvcParam.uiIntraPeriod = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("MaxNalSize") == 0) { pSvcParam.uiMaxNalSize = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("SpsPpsIDStrategy") == 0) { int32_t iValue = atoi (strTag[1].c_str()); switch (iValue) { case 0: pSvcParam.eSpsPpsIdStrategy = CONSTANT_ID; break; case 0x01: pSvcParam.eSpsPpsIdStrategy = INCREASING_ID; break; case 0x02: pSvcParam.eSpsPpsIdStrategy = SPS_LISTING; break; case 0x03: pSvcParam.eSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING; break; case 0x06: pSvcParam.eSpsPpsIdStrategy = SPS_PPS_LISTING; break; default: pSvcParam.eSpsPpsIdStrategy = CONSTANT_ID; break; } } else if (strTag[0].compare ("EnableMultiBsFile") == 0) { sFileSet.bEnableMultiBsFile = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableScalableSEI") == 0) { pSvcParam.bEnableSSEI = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableFrameCropping") == 0) { pSvcParam.bEnableFrameCroppingFlag = (atoi (strTag[1].c_str()) != 0); } else if (strTag[0].compare ("EntropyCodingModeFlag") == 0) { pSvcParam.iEntropyCodingModeFlag = (atoi (strTag[1].c_str()) != 0); } else if (strTag[0].compare ("ComplexityMode") == 0) { pSvcParam.iComplexityMode = (ECOMPLEXITY_MODE) (atoi (strTag[1].c_str())); } else if (strTag[0].compare ("LoopFilterDisableIDC") == 0) { pSvcParam.iLoopFilterDisableIdc = (int8_t)atoi (strTag[1].c_str()); if (pSvcParam.iLoopFilterDisableIdc > 6 || pSvcParam.iLoopFilterDisableIdc < 0) { fprintf (stderr, "Invalid parameter in iLoopFilterDisableIdc: %d.\n", pSvcParam.iLoopFilterDisableIdc); iRet = 1; break; } } else if (strTag[0].compare ("LoopFilterAlphaC0Offset") == 0) { pSvcParam.iLoopFilterAlphaC0Offset = (int8_t)atoi (strTag[1].c_str()); if (pSvcParam.iLoopFilterAlphaC0Offset < -6) pSvcParam.iLoopFilterAlphaC0Offset = -6; else if (pSvcParam.iLoopFilterAlphaC0Offset > 6) pSvcParam.iLoopFilterAlphaC0Offset = 6; } else if (strTag[0].compare ("LoopFilterBetaOffset") == 0) { pSvcParam.iLoopFilterBetaOffset = (int8_t)atoi (strTag[1].c_str()); if (pSvcParam.iLoopFilterBetaOffset < -6) pSvcParam.iLoopFilterBetaOffset = -6; else if (pSvcParam.iLoopFilterBetaOffset > 6) pSvcParam.iLoopFilterBetaOffset = 6; } else if (strTag[0].compare ("MultipleThreadIdc") == 0) { // # 0: auto(dynamic imp. internal encoder); 1: multiple threads imp. disabled; > 1: count number of threads; pSvcParam.iMultipleThreadIdc = atoi (strTag[1].c_str()); if (pSvcParam.iMultipleThreadIdc < 0) pSvcParam.iMultipleThreadIdc = 0; else if (pSvcParam.iMultipleThreadIdc > MAX_THREADS_NUM) pSvcParam.iMultipleThreadIdc = MAX_THREADS_NUM; } else if (strTag[0].compare ("UseLoadBalancing") == 0) { pSvcParam.bUseLoadBalancing = (atoi (strTag[1].c_str())) ? true : false; } else if (strTag[0].compare ("RCMode") == 0) { pSvcParam.iRCMode = (RC_MODES) atoi (strTag[1].c_str()); } else if (strTag[0].compare ("TargetBitrate") == 0) { pSvcParam.iTargetBitrate = 1000 * atoi (strTag[1].c_str()); if ((pSvcParam.iRCMode != RC_OFF_MODE) && pSvcParam.iTargetBitrate <= 0) { fprintf (stderr, "Invalid target bitrate setting due to RC enabled. Check TargetBitrate field please!\n"); return 1; } } else if (strTag[0].compare ("MaxOverallBitrate") == 0) { pSvcParam.iMaxBitrate = 1000 * atoi (strTag[1].c_str()); if ((pSvcParam.iRCMode != RC_OFF_MODE) && pSvcParam.iMaxBitrate < 0) { fprintf (stderr, "Invalid max overall bitrate setting due to RC enabled. Check MaxOverallBitrate field please!\n"); return 1; } } else if (strTag[0].compare ("MaxQp") == 0) { pSvcParam.iMaxQp = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("MinQp") == 0) { pSvcParam.iMinQp = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("EnableDenoise") == 0) { pSvcParam.bEnableDenoise = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableSceneChangeDetection") == 0) { pSvcParam.bEnableSceneChangeDetect = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableBackgroundDetection") == 0) { pSvcParam.bEnableBackgroundDetection = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableAdaptiveQuantization") == 0) { pSvcParam.bEnableAdaptiveQuant = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableFrameSkip") == 0) { pSvcParam.bEnableFrameSkip = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("EnableLongTermReference") == 0) { pSvcParam.bEnableLongTermReference = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("LongTermReferenceNumber") == 0) { pSvcParam.iLTRRefNum = atoi (strTag[1].c_str()); } else if (strTag[0].compare ("LtrMarkPeriod") == 0) { pSvcParam.iLtrMarkPeriod = (uint32_t)atoi (strTag[1].c_str()); } else if (strTag[0].compare ("LosslessLink") == 0) { pSvcParam.bIsLosslessLink = atoi (strTag[1].c_str()) ? true : false; } else if (strTag[0].compare ("NumLayers") == 0) { pSvcParam.iSpatialLayerNum = (int8_t)atoi (strTag[1].c_str()); if (pSvcParam.iSpatialLayerNum > MAX_DEPENDENCY_LAYER || pSvcParam.iSpatialLayerNum <= 0) { fprintf (stderr, "Invalid parameter in iSpatialLayerNum: %d.\n", pSvcParam.iSpatialLayerNum); iRet = 1; break; } } else if (strTag[0].compare ("LayerCfg") == 0) { if (strTag[1].length() > 0) sFileSet.strLayerCfgFile[iLayerCount] = strTag[1]; // pSvcParam.sDependencyLayers[iLayerCount].uiDependencyId = iLayerCount; ++ iLayerCount; } else if (strTag[0].compare ("PrefixNALAddingCtrl") == 0) { int ctrl_flag = atoi (strTag[1].c_str()); if (ctrl_flag > 1) ctrl_flag = 1; else if (ctrl_flag < 0) ctrl_flag = 0; pSvcParam.bPrefixNalAddingCtrl = ctrl_flag ? true : false; } } } const int8_t kiActualLayerNum = WELS_MIN (pSvcParam.iSpatialLayerNum, iLayerCount); if (pSvcParam.iSpatialLayerNum > kiActualLayerNum) { // fixed number of dependency layer due to parameter error in settings pSvcParam.iSpatialLayerNum = kiActualLayerNum; } assert (kiActualLayerNum <= MAX_DEPENDENCY_LAYER); for (int8_t iLayer = 0; iLayer < kiActualLayerNum; ++ iLayer) { CReadConfig cRdLayerCfg (sFileSet.strLayerCfgFile[iLayer]); if (-1 == ParseLayerConfig (cRdLayerCfg, iLayer, pSvcParam, sFileSet)) { iRet = 1; break; } } return iRet; } void PrintHelp() { printf ("\n Wels SVC Encoder Usage:\n\n"); printf (" Syntax: welsenc.exe -h\n"); printf (" Syntax: welsenc.exe welsenc.cfg\n"); printf (" Syntax: welsenc.exe welsenc.cfg [options]\n"); printf ("\n Supported Options:\n"); printf (" -bf Bit Stream File\n"); printf (" -org Original file, example: -org src.yuv\n"); printf (" -sw the source width\n"); printf (" -sh the source height\n"); printf (" -utype usage type\n"); printf (" -savc simulcast avc\n"); printf (" -frms Number of total frames to be encoded\n"); printf (" -frin input frame rate\n"); printf (" -numtl Temporal layer number (default: 1)\n"); printf (" -iper Intra period (default: -1) : must be a power of 2 of GOP size (or -1)\n"); printf (" -nalsize the Maximum NAL size. which should be larger than the each layer slicesize when slice mode equals to SM_SIZELIMITED_SLICE\n"); printf (" -spsid SPS/PPS id strategy: 0:const, 1: increase, 2: sps list, 3: sps list and pps increase, 4: sps/pps list\n"); printf (" -cabac Entropy coding mode(0:cavlc 1:cabac \n"); printf (" -complexity Complexity mode (default: 0),0: low complexity, 1: medium complexity, 2: high complexity\n"); printf (" -denois Control denoising (default: 0)\n"); printf (" -scene Control scene change detection (default: 0)\n"); printf (" -bgd Control background detection (default: 0)\n"); printf (" -aq Control adaptive quantization (default: 0)\n"); printf (" -ltr Control long term reference (default: 0)\n"); printf (" -ltrnum Control the number of long term reference((1-4):screen LTR,(1-2):video LTR \n"); printf (" -ltrper Control the long term reference marking period \n"); printf (" -threadIdc 0: auto(dynamic imp. internal encoder); 1: multiple threads imp. disabled; > 1: count number of threads \n"); printf (" -loadbalancing 0: turn off loadbalancing between slices when multi-threading available; 1: (default value) turn on loadbalancing between slices when multi-threading available\n"); printf (" -deblockIdc Loop filter idc (0: on, 1: off, \n"); printf (" -alphaOffset AlphaOffset(-6..+6): valid range \n"); printf (" -betaOffset BetaOffset (-6..+6): valid range\n"); printf (" -rc rate control mode: -1-rc off; 0-quality mode; 1-bitrate mode; 2: buffer based mode,can't control bitrate; 3: bitrate mode based on timestamp input;\n"); printf (" -tarb Overall target bitrate\n"); printf (" -maxbrTotal Overall max bitrate\n"); printf (" -maxqp Maximum Qp (default: %d, or for screen content usage: %d)\n", QP_MAX_VALUE, MAX_SCREEN_QP); printf (" -minqp Minimum Qp (default: %d, or for screen content usage: %d)\n", QP_MIN_VALUE, MIN_SCREEN_QP); printf (" -numl Number Of Layers: Must exist with layer_cfg file and the number of input layer_cfg file must equal to the value set by this command\n"); printf (" The options below are layer-based: (need to be set with layer id)\n"); printf (" -lconfig (Layer) (spatial layer configure file)\n"); printf (" -drec (Layer) (reconstruction file);example: -drec 0 rec.yuv. Setting the reconstruction file, this will only functioning when dumping reconstruction is enabled\n"); printf (" -dprofile (Layer) (layer profile);example: -dprofile 0 66. Setting the layer profile, this should be the same for all layers\n"); printf (" -dw (Layer) (output width)\n"); printf (" -dh (Layer) (output height)\n"); printf (" -frout (Layer) (output frame rate)\n"); printf (" -lqp (Layer) (base quality layer qp : must work with -ldeltaqp or -lqparr)\n"); printf (" -ltarb (Layer) (spatial layer target bitrate)\n"); printf (" -lmaxb (Layer) (spatial layer max bitrate)\n"); printf (" -slcmd (Layer) (spatial layer slice mode): pls refer to layerX.cfg for details ( -slcnum: set target slice num; -slcsize: set target slice size constraint ; -slcmbnum: set the first slice mb num under some slice modes) \n"); printf (" -trace (Level)\n"); printf ("\n"); } int ParseCommandLine (int argc, char** argv, SSourcePicture* pSrcPic, SEncParamExt& pSvcParam, SFilesSet& sFileSet) { char* pCommand = NULL; SLayerPEncCtx sLayerCtx[MAX_SPATIAL_LAYER_NUM]; int n = 0; string str_ ("SlicesAssign"); while (n < argc) { pCommand = argv[n++]; if (!strcmp (pCommand, "-bf") && (n < argc)) sFileSet.strBsFile.assign (argv[n++]); else if (!strcmp (pCommand, "-utype") && (n < argc)) pSvcParam.iUsageType = (EUsageType)atoi (argv[n++]); else if (!strcmp (pCommand, "-savc") && (n < argc)) pSvcParam.bSimulcastAVC = atoi (argv[n++]) ? true : false; else if (!strcmp (pCommand, "-org") && (n < argc)) sFileSet.strSeqFile.assign (argv[n++]); else if (!strcmp (pCommand, "-sw") && (n < argc))//source width pSrcPic->iPicWidth = atoi (argv[n++]); else if (!strcmp (pCommand, "-sh") && (n < argc))//source height pSrcPic->iPicHeight = atoi (argv[n++]); else if (!strcmp (pCommand, "-frms") && (n < argc)) sFileSet.uiFrameToBeCoded = atoi (argv[n++]); else if (!strcmp (pCommand, "-frin") && (n < argc)) pSvcParam.fMaxFrameRate = (float) atof (argv[n++]); else if (!strcmp (pCommand, "-numtl") && (n < argc)) pSvcParam.iTemporalLayerNum = atoi (argv[n++]); else if (!strcmp (pCommand, "-mfile") && (n < argc)) sFileSet.bEnableMultiBsFile = atoi (argv[n++]) ? true : false; else if (!strcmp (pCommand, "-iper") && (n < argc)) pSvcParam.uiIntraPeriod = atoi (argv[n++]); else if (!strcmp (pCommand, "-nalsize") && (n < argc)) pSvcParam.uiMaxNalSize = atoi (argv[n++]); else if (!strcmp (pCommand, "-spsid") && (n < argc)) { int32_t iValue = atoi (argv[n++]); switch (iValue) { case 0: pSvcParam.eSpsPpsIdStrategy = CONSTANT_ID; break; case 0x01: pSvcParam.eSpsPpsIdStrategy = INCREASING_ID; break; case 0x02: