/* Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved. All
 * information contained herein is proprietary and confidential to NVIDIA
 * Corporation.  Any use, reproduction, or disclosure without the written
 * permission of NVIDIA Corporation is prohibited.
 */

/* Standard headers */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

/* Nvidia headers */
#include "cmdline.h"
#include "log_utils.h"
#include "misc_utils.h"
#include "config_parser.h"

/* see cmdline.h for details */
void PrintUsage()
{
    LOG_MSG("nvmimg_ldc is NvMedia Lens Distortion Correction test program\n");
    LOG_MSG("Usage: nvmimg_ldc [options]\n");
    LOG_MSG("Options:\n");
    LOG_MSG("-h           Prints usage\n");
    LOG_MSG("-v  [level]  Verbosity Level = 0(Err), 1(Warn), 2(Info), 3(Debug)\n");
    LOG_MSG("-cf [config] LDC config file. Path length limited to %u chars\n", FILE_NAME_SIZE);
}

SectionMap sectionsMap[] = {
    {SECTION_NONE, "", 0, 0} /* Has to be the last item - specifies the end of array */
};

/* see cmdline.h for details */
int ParseArgs(int argc, char *argv[], TestArgs *args)
{
    NvMediaBool bLastArg = NVMEDIA_FALSE;
    NvMediaBool bDataAvailable = NVMEDIA_FALSE;
    NvMediaStatus status = NVMEDIA_STATUS_OK;
    char *filename = NULL;
    int i;
    NvMediaLDCInitParams *init = &(args->initParams);
    NvMediaGeoTransParams *geoTrans = &(init->geoTransParams);
    NvMediaCameraModel *cam = &(geoTrans->cameraModel);
    NvMediaLDCRegionConfig *regConf = &(geoTrans->regionConfig);
    NvMediaLDCBitMaskMap *btMsk = &(geoTrans->bitMaskMap);
    NvMediaTNR3Params *tnr3 = &(init->tnr3Params);
    NvMediaTNR2Params *tnr2 = &(init->tnr2Params);
    NvMediaLDCSparseWarpMap *sparse = &(args->SparseWarpMap);
    NvMediaLDCCtrlParams *ctrl = &(args->ldcCtrlParams);

    /* ConfigParamsMap
     * See nvmedia_ldc.h and sample config file(s) for details.
     */
    ConfigParamsMap paramsMap[] = {
        /*ParamName,             &args->variableName,          paramType,     D, LimitType,   Mn, Mx, CharSize,       p2C, section   */
        {"numFrames",            &args->numFrames,             TYPE_UINT,     1, LIMITS_MIN,  1,  0,  0,              0, SECTION_NONE},
        {"inputfile",            &args->infile,                TYPE_CHAR_ARR, 0, LIMITS_NONE, 0,  0,  FILE_NAME_SIZE, 0, SECTION_NONE},
        {"outputFile",           &args->outfile,               TYPE_CHAR_ARR, 0, LIMITS_NONE, 0,  0,  FILE_NAME_SIZE, 0, SECTION_NONE},
        {"xSobelFile",           &args->xsobelfile,            TYPE_CHAR_ARR, 0, LIMITS_NONE, 0,  0,  FILE_NAME_SIZE, 0, SECTION_NONE},
        {"downSampleFile",       &args->downsamplefile,        TYPE_CHAR_ARR, 0, LIMITS_NONE, 0,  0,  FILE_NAME_SIZE, 0, SECTION_NONE},
        {"subSampling",          &args->subSampling,           TYPE_USHORT,   0, LIMITS_BOTH, 0,  4,  0,              0, SECTION_NONE},
        {"bitsPerComponent",     &args->bitsPerComponent,      TYPE_USHORT,   0, LIMITS_BOTH, 1,  6,  0,              0, SECTION_NONE},
        {"UVorder",              &args->UVorder,               TYPE_USHORT,   0, LIMITS_BOTH, 0,  1,  0,              0, SECTION_NONE},
        {"xSobelWidth",          &args->xSobelWidth,           TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        {"xSobelHeight",         &args->xSobelHeight,          TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        /*NvMediaLDC Configuration*/
        /*NvMediaLDCCreate*/
        /*ParamName,             &args->variableName,          paramType,     D, LimitType,   Mn, Mx, CharSize,       p2C, section   */
        /*src*/
        {"srcWidth",             &args->srcWidth,              TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        {"srcHeight",            &args->srcHeight,             TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        /*srcRect*/
        {"srcRectx0",            &args->srcRect.x0,            TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        {"srcRecty0",            &args->srcRect.y0,            TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        {"srcRectx1",            &args->srcRect.x1,            TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        {"srcRecty1",            &args->srcRect.y1,            TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        /*dst*/
        {"dstWidth",             &args->dstWidth,              TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        {"dstHeight",            &args->dstHeight,             TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        /*dstRect*/
        {"dstRectx0",            &args->dstRect.x0,            TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        {"dstRecty0",            &args->dstRect.y0,            TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        {"dstRectx1",            &args->dstRect.x1,            TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        {"dstRecty1",            &args->dstRect.y1,            TYPE_USHORT,   0, LIMITS_MIN,  0,  0,  0,              0, SECTION_NONE},
        /*NvMediaLDCInitParams*/
        /*ParamName,             &args->variableName,          paramType,     D, LimitType,   Mn, Mx, CharSize,       p2C, section   */
        {"ldcMode",              &init->ldcMode,               TYPE_UINT,     0, LIMITS_BOTH, 0,  3,  0,              0, SECTION_NONE},
        /*NvMediaGeoTransParams*/
        {"geoTransMode",         &geoTrans->geoTransMode,      TYPE_UINT,     0, LIMITS_BOTH, 0,  3,  0,              0, SECTION_NONE},
        {"filter",               &geoTrans->filter,            TYPE_UINT,     0, LIMITS_BOTH, 0,  2,  0,              0, SECTION_NONE},
        /*NvMediaCameraModel*/
        {"model",                &cam->model,                  TYPE_UINT,     0, LIMITS_BOTH, 0,  4,  0,              0, SECTION_NONE},
        /*distCoeffs*/
        {"k1",                   &cam->distCoeffs.k1,          TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"k2",                   &cam->distCoeffs.k2,          TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"p1",                   &cam->distCoeffs.p1,          TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"p2",                   &cam->distCoeffs.p2,          TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"k3",                   &cam->distCoeffs.k3,          TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"k4",                   &cam->distCoeffs.k4,          TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"k5",                   &cam->distCoeffs.k5,          TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"k6",                   &cam->distCoeffs.k6,          TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        /*NvMediaCamIntriParams K*/
        {"fx",                   &cam->K.fx,                   TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"fy",                   &cam->K.fy,                   TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"cx",                   &cam->K.cx,                   TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"cy",                   &cam->K.cy,                   TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        /*Rotation Matrix R*/
        {"R00",                  &cam->R[0][0],                TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"R01",                  &cam->R[0][1],                TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"R02",                  &cam->R[0][2],                TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"R10",                  &cam->R[1][0],                TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"R11",                  &cam->R[1][1],                TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"R12",                  &cam->R[1][2],                TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"R20",                  &cam->R[2][0],                TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"R21",                  &cam->R[2][1],                TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"R22",                  &cam->R[2][2],                TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        /*ParamName,             &args->variableName,          paramType,     D, LimitType,   Mn, Mx, CharSize,       p2C, section   */
        /*Translation vector T*/
        {"T0",                   &cam->T[0],                   TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"T1",                   &cam->T[1],                   TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"T2",                   &cam->T[2],                   TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        /*NvMediaCamIntriParams targetK*/
        {"targetKfx",            &cam->targetK.fx,             TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"targetKfy",            &cam->targetK.fy,             TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"targetKcx",            &cam->targetK.cx,             TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"targetKcy",            &cam->targetK.cy,             TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        /*Perspective Matrix ptMatrix*/
        {"ptMatrix00",           &geoTrans->ptMatrix[0][0],    TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"ptMatrix01",           &geoTrans->ptMatrix[0][1],    TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"ptMatrix02",           &geoTrans->ptMatrix[0][2],    TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"ptMatrix10",           &geoTrans->ptMatrix[1][0],    TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"ptMatrix11",           &geoTrans->ptMatrix[1][1],    TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"ptMatrix12",           &geoTrans->ptMatrix[1][2],    TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"ptMatrix20",           &geoTrans->ptMatrix[2][0],    TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"ptMatrix21",           &geoTrans->ptMatrix[2][1],    TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"ptMatrix22",           &geoTrans->ptMatrix[2][2],    TYPE_FLOAT,    0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        /*ParamName,             &args->variableName,          paramType,     D, LimitType,   Mn, Mx, CharSize,       p2C, section   */
        /*NvMediaLDCRegionConfig regionConfig*/
        {"numHorRegion",         &regConf->numHorRegion,       TYPE_UCHAR,    0, LIMITS_BOTH, 1,  4, 0,               0, SECTION_NONE},
        {"numVerRegion",         &regConf->numVerRegion,       TYPE_UCHAR,    0, LIMITS_BOTH, 1,  4, 0,               0, SECTION_NONE},
        {"horRegionWidth0",      &regConf->horRegionWidth[0],  TYPE_USHORT,   0, LIMITS_MIN,  0,  1, 0,               0, SECTION_NONE},
        {"horRegionWidth1",      &regConf->horRegionWidth[1],  TYPE_USHORT,   0, LIMITS_MIN,  0,  1, 0,               0, SECTION_NONE},
        {"horRegionWidth2",      &regConf->horRegionWidth[2],  TYPE_USHORT,   0, LIMITS_MIN,  0,  1, 0,               0, SECTION_NONE},
        {"horRegionWidth3",      &regConf->horRegionWidth[3],  TYPE_USHORT,   0, LIMITS_MIN,  0,  1, 0,               0, SECTION_NONE},
        {"verRegionHeight0",     &regConf->verRegionHeight[0], TYPE_USHORT,   0, LIMITS_MIN,  0,  1, 0,               0, SECTION_NONE},
        {"verRegionHeight1",     &regConf->verRegionHeight[1], TYPE_USHORT,   0, LIMITS_MIN,  0,  1, 0,               0, SECTION_NONE},
        {"verRegionHeight2",     &regConf->verRegionHeight[2], TYPE_USHORT,   0, LIMITS_MIN,  0,  1, 0,               0, SECTION_NONE},
        {"verRegionHeight3",     &regConf->verRegionHeight[3], TYPE_USHORT,   0, LIMITS_MIN,  0,  1, 0,               0, SECTION_NONE},
        {"log2horSpace0",        &regConf->log2horSpace[0],    TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"log2horSpace1",        &regConf->log2horSpace[1],    TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"log2horSpace2",        &regConf->log2horSpace[2],    TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"log2horSpace3",        &regConf->log2horSpace[3],    TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"log2verSpace0",        &regConf->log2verSpace[0],    TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"log2verSpace1",        &regConf->log2verSpace[1],    TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"log2verSpace2",        &regConf->log2verSpace[2],    TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"log2verSpace3",        &regConf->log2verSpace[3],    TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        /*ParamName,             &args->variableName,          paramType,     D, LimitType,   Mn, Mx, CharSize,       p2C, section   */
        /*bitMaskEnable*/
        {"bitMaskEnable",        &geoTrans->bitMaskEnable,     TYPE_UINT,     0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        /*NvMediaLDCBitMaskMap bitMaskMap*/
        {"bitMaskwidth",         &btMsk->width,                TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"bitMaskheight",        &btMsk->height,               TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"bitMaskSurfaceFile",   &args->bitMaskFile,           TYPE_CHAR_ARR, 0, LIMITS_NONE, 0,  0, FILE_NAME_SIZE,  0, SECTION_NONE},
        {"maskedPixelFillColor", &btMsk->maskedPixelFillColor, TYPE_UINT,     0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"maskY",                &geoTrans->maskY,             TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"maskU",                &geoTrans->maskU,             TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"maskV",                &geoTrans->maskV,             TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        /*NvMediaTNR3Params tnr3Params*/
        {"spatialSigmaLuma",     &tnr3->spatialSigmaLuma,      TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"spatialSigmaChroma",   &tnr3->spatialSigmaChroma,    TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"rangeSigmaLuma",       &tnr3->rangeSigmaLuma,        TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"rangeSigmaChroma",     &tnr3->rangeSigmaChroma,      TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"sadMultiplier",        &tnr3->sadMultiplier,         TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"sadWeightLuma",        &tnr3->sadWeightLuma,         TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"alphaSmoothEnable",    &tnr3->alphaSmoothEnable,     TYPE_UINT,     0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"alphaIncreaseCap",     &tnr3->alphaIncreaseCap,      TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"alphaScaleIIR",        &tnr3->alphaScaleIIR,         TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"alphaMaxLuma",         &tnr3->alphaMaxLuma,          TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"alphaMinLuma",         &tnr3->alphaMinLuma,          TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"alphaMaxChroma",       &tnr3->alphaMaxChroma,        TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"alphaMinChroma",       &tnr3->alphaMinChroma,        TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"betaX1",               &tnr3->betaX1,                TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"betaX2",               &tnr3->betaX2,                TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"minBeta",              &tnr3->minBeta,               TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"maxBeta",              &tnr3->maxBeta,               TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        /*ParamName,             &args->variableName,          paramType,     D, LimitType,   Mn, Mx, CharSize,       p2C, section   */
        /*NvMediaLDCFeedSparseWarpMap map*/
        {"numHorPoints",         &sparse->numHorPoints,        TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"numVerPoints",         &sparse->numVerPoints,        TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"mapStride",            &sparse->mapStride,           TYPE_USHORT,   0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE},
        {"sparseMapFile",        &args->SparseWarpMapFile,     TYPE_CHAR_ARR, 0, LIMITS_NONE, 0,  0, FILE_NAME_SIZE,  0, SECTION_NONE},
        {"dataFormat",           &sparse->dataFormat,          TYPE_UINT,     0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        /*NvMediaLDCCtrlParams ldcCtrlParams*/
        {"xSobelMode",           &ctrl->xSobelMode,            TYPE_UINT,     0, LIMITS_BOTH, 0,  3, 0,               0, SECTION_NONE},
        {"bUpdateTNR3Params",    &args->bUpdateTNR3Params,     TYPE_UINT,     0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        /*NvMediaTNR2Params tnr2Params*/
        {"noiseReduction",       &tnr2->noiseReduction,        TYPE_FLOAT,    0, LIMITS_BOTH, 0,  1, 0,               0, SECTION_NONE},
        {"noiseReductionAlgorithm", &tnr2->noiseReductionAlgorithm, TYPE_UINT,   0, LIMITS_BOTH, 0, 6, 0,            0, SECTION_NONE},
        /*End of the array */
        {NULL,                   NULL,                         TYPE_UINT,     0, LIMITS_NONE, 0,  0, 0,               0, SECTION_NONE}
    };

    for (i = 1; i < argc; i++) {
        /* check if this is the last argument*/
        bLastArg = ((argc - i) == 1);

        /* check if there is data available to be parsed following the option*/
        bDataAvailable = (!bLastArg) && !(argv[i+1][0] == '-');

        if (argv[i][0] == '-') {
            if (strcmp(&argv[i][1], "h") == 0) {
                return -1;
            }
            else if (strcmp(&argv[i][1], "v") == 0) {
                if (bDataAvailable) {
                    args->logLevel = atoi(argv[++i]);
                    if (args->logLevel < LEVEL_ERR || args->logLevel > LEVEL_DBG) {
                        LOG_ERR("ParseArgs: Invalid logging level chosen (%d).\n", args->logLevel);
                        LOG_ERR("           default logging level is LEVEL_ERR \n");
                        args->logLevel = LEVEL_ERR;
                    }
                }
                SetLogLevel(args->logLevel);
            }
            else if (strcmp(&argv[i][1], "cf") == 0) {
                /* Init Parser Map*/
                LOG_INFO("ParseArgs: Initializing Parser Params Map\n");
                status = ConfigParser_InitParamsMap(paramsMap);
                if (status != NVMEDIA_STATUS_OK) {
                    LOG_ERR("ERR: ConfigParser_InitParamsMap failed! status:%x\n", status);
                    return -1;
                }

                filename = argv[++i];
                if (!filename) {
                    LOG_ERR("ERR: Invalid config file name\n");
                    return -1;
                }

                LOG_INFO("ParseArgs: Parsing config file %s\n", filename);
                status = ConfigParser_ParseFile(paramsMap, 1, sectionsMap, filename);
                if (status != NVMEDIA_STATUS_OK) {
                    LOG_ERR("ERR: Failed to parse config file. status:%x\n", status);
                    return -1;
                }
            }
            else
            {
                LOG_ERR("ERR: option %c is not supported and ignored.\n", argv[i][1]);
            }
        }
    }

    LOG_INFO("ParseArgs: Validating params from config file\n");
    status = ConfigParser_ValidateParams(paramsMap, sectionsMap);
    if (status != NVMEDIA_STATUS_OK) {
        LOG_ERR("ERR: Some of the params in config file are invalid.\n");
        /* Ignore the failure and let library handle any exceptions */
    }

    if (args->logLevel > LEVEL_ERR) {
        LOG_INFO("ParseArgs: Printing params from config file\n");
        ConfigParser_DisplayParams(paramsMap, sectionsMap);
    }

    return 0;
}

