/******************************************************************************\
Copyright (c) 2005-2020, Intel Corporation
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. 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.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

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.

This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/

#include "sample_vpp_utils.h"
#include <string>
#include <algorithm>
#include <cctype>
#include <sstream>
#include <fstream>
#include "version.h"

#define VAL_CHECK(val) {if (val) return MFX_ERR_UNKNOWN;}

#ifndef MFX_VERSION
#error MFX_VERSION not defined
#endif

void vppPrintHelp(const msdk_char *strAppName, const msdk_char *strErrorMessage)
{
    msdk_printf(MSDK_STRING("Intel(R) Media SDK VPP Sample version %s\n"), GetMSDKSampleVersion().c_str());
    if (strErrorMessage)
    {
        msdk_printf(MSDK_STRING("Error: %s\n"), strErrorMessage);
    }

msdk_printf(MSDK_STRING("Usage: %s [Options] -i InputFile -o OutputFile\n"), strAppName);

msdk_printf(MSDK_STRING("Options: \n"));
msdk_printf(MSDK_STRING("   [-lib  type]                - type of used library. sw, hw (def: sw)\n\n"));
#if defined(LINUX32) || defined(LINUX64)
msdk_printf(MSDK_STRING("   [-device /path/to/device]   - set graphics device for processing\n"));
msdk_printf(MSDK_STRING("                                  For example: '-device /dev/dri/card0'\n"));
msdk_printf(MSDK_STRING("                                               '-device /dev/dri/renderD128'\n"));
msdk_printf(MSDK_STRING("                                  If not specified, defaults to the first Intel device found on the system\n\n"));
#endif
#if (defined(_WIN64) || defined(_WIN32)) && (MFX_VERSION >= 1031)
msdk_printf(MSDK_STRING("   [-dGfx]                     - preffer processing on dGfx (by default system decides)\n"));
msdk_printf(MSDK_STRING("   [-iGfx]                     - preffer processing on iGfx (by default system decides)\n"));
#endif
#if defined(D3D_SURFACES_SUPPORT)
msdk_printf(MSDK_STRING("   [-d3d]                      - use d3d9 surfaces\n\n"));
#endif
#if MFX_D3D11_SUPPORT
msdk_printf(MSDK_STRING("   [-d3d11]                    - use d3d11 surfaces\n\n"));
#endif
#ifdef LIBVA_SUPPORT
msdk_printf(MSDK_STRING("   [-vaapi]                    - work with vaapi surfaces\n\n"));
#endif
msdk_printf(MSDK_STRING("   [-plugin_guid GUID]\n"));
msdk_printf(MSDK_STRING("   [-p GUID]                   - use VPP plug-in with specified GUID\n\n"));
msdk_printf(MSDK_STRING("   [-extapi]                   - use RunFrameVPPAsyncEx instead of RunFrameVPPAsync. Need for PTIR.\n\n"));
msdk_printf(MSDK_STRING("   [-gpu_copy]                 - Specify GPU copy mode. This option triggers using of InitEX instead of Init.\n\n"));

msdk_printf(MSDK_STRING("   [-sw   width]               - width  of src video (def: 352)\n"));
msdk_printf(MSDK_STRING("   [-sh   height]              - height of src video (def: 288)\n"));
msdk_printf(MSDK_STRING("   [-scrX  x]                  - cropX  of src video (def: 0)\n"));
msdk_printf(MSDK_STRING("   [-scrY  y]                  - cropY  of src video (def: 0)\n"));
msdk_printf(MSDK_STRING("   [-scrW  w]                  - cropW  of src video (def: width)\n"));
msdk_printf(MSDK_STRING("   [-scrH  h]                  - cropH  of src video (def: height)\n"));
msdk_printf(MSDK_STRING("   [-sf   frameRate]           - frame rate of src video (def: 30.0)\n"));
msdk_printf(MSDK_STRING("   [-scc  format]              - format (FourCC) of src video (def: nv12. support i420|nv12|yv12|yuy2|rgb565|rgb3|rgb4|imc3|yuv400|yuv411|yuv422h|yuv422v|yuv444|uyvy|ayuv|p010|y210|y410|p016|y216|y416)\n"));
msdk_printf(MSDK_STRING("   [-sbitshift 0|1]            - shift data to right or keep it the same way as in Microsoft's P010\n"));
msdk_printf(MSDK_STRING("   [-sbitdepthluma value]      - shift luma channel to right to \"16 - value\" bytes\n"));
msdk_printf(MSDK_STRING("   [-sbitdepthchroma value]    - shift chroma channel to right to \"16 - value\" bytes\n"));

msdk_printf(MSDK_STRING("   [-spic value]               - picture structure of src video\n"));
msdk_printf(MSDK_STRING("                                 0 - interlaced top    field first\n"));
msdk_printf(MSDK_STRING("                                 2 - interlaced bottom field first\n"));
msdk_printf(MSDK_STRING("                                 3 - single field\n"));
msdk_printf(MSDK_STRING("                                 1 - progressive (default)\n"));
msdk_printf(MSDK_STRING("                                -1 - unknown\n\n"));

msdk_printf(MSDK_STRING("   [-dw  width]                - width  of dst video (def: 352)\n"));
msdk_printf(MSDK_STRING("   [-dh  height]               - height of dst video (def: 288)\n"));
msdk_printf(MSDK_STRING("   [-dcrX  x]                  - cropX  of dst video (def: 0)\n"));
msdk_printf(MSDK_STRING("   [-dcrY  y]                  - cropY  of dst video (def: 0)\n"));
msdk_printf(MSDK_STRING("   [-dcrW  w]                  - cropW  of dst video (def: width)\n"));
msdk_printf(MSDK_STRING("   [-dcrH  h]                  - cropH  of dst video (def: height)\n"));
msdk_printf(MSDK_STRING("   [-df  frameRate]            - frame rate of dst video (def: 30.0)\n"));
#if (MFX_VERSION >= 1031)
msdk_printf(MSDK_STRING("   [-dcc format]               - format (FourCC) of dst video (def: nv12. support i420|nv12|yuy2|rgb4|rgbp|yv12|ayuv|a2rgb10|y210|y410|p016|y216|y416)\n"));
#elif (MFX_VERSION >= 1027)
msdk_printf(MSDK_STRING("   [-dcc format]               - format (FourCC) of dst video (def: nv12. support i420|nv12|yuy2|rgb4|rgbp|yv12|ayuv|a2rgb10|y210|y410)\n"));
#else
msdk_printf(MSDK_STRING("   [-dcc format]               - format (FourCC) of dst video (def: nv12. support i420|nv12|yuy2|rgb4|rgbp|yv12|ayuv|a2rgb10)\n"));
#endif
msdk_printf(MSDK_STRING("   [-dbitshift 0|1]            - shift data to right or keep it the same way as in Microsoft's P010\n"));
msdk_printf(MSDK_STRING("   [-dbitdepthluma value]      - shift luma channel to left to \"16 - value\" bytes\n"));
msdk_printf(MSDK_STRING("   [-dbitdepthchroma value]    - shift chroma channel to left to \"16 - value\" bytes\n"));

msdk_printf(MSDK_STRING("   [-dpic value]               - picture structure of dst video\n"));
msdk_printf(MSDK_STRING("                                 0 - interlaced top    field first\n"));
msdk_printf(MSDK_STRING("                                 2 - interlaced bottom field first\n"));
msdk_printf(MSDK_STRING("                                 3 - single field\n"));
msdk_printf(MSDK_STRING("                                 1 - progressive (default)\n"));
msdk_printf(MSDK_STRING("                                -1 - unknown\n\n"));

msdk_printf(MSDK_STRING("   Video Composition\n"));
msdk_printf(MSDK_STRING("   [-composite parameters_file] - composite several input files in one output. The syntax of the parameters file is:\n"));    msdk_printf(MSDK_STRING("                                  stream=<video file name>\n"));
msdk_printf(MSDK_STRING("                                  width=<input video width>\n"));
msdk_printf(MSDK_STRING("                                  height=<input video height>\n"));
msdk_printf(MSDK_STRING("                                  cropx=<input cropX (def: 0)>\n"));
msdk_printf(MSDK_STRING("                                  cropy=<input cropY (def: 0)>\n"));
msdk_printf(MSDK_STRING("                                  cropw=<input cropW (def: width)>\n"));
msdk_printf(MSDK_STRING("                                  croph=<input cropH (def: height)>\n"));
msdk_printf(MSDK_STRING("                                  framerate=<input frame rate (def: 30.0)>\n"));
msdk_printf(MSDK_STRING("                                  fourcc=<format (FourCC) of input video (def: nv12. support nv12|rgb4)>\n"));
msdk_printf(MSDK_STRING("                                  picstruct=<picture structure of input video,\n"));
msdk_printf(MSDK_STRING("                                             0 = interlaced top    field first\n"));
msdk_printf(MSDK_STRING("                                             2 = interlaced bottom field first\n"));
msdk_printf(MSDK_STRING("                                             3 = single field\n"));
msdk_printf(MSDK_STRING("                                             1 = progressive (default)>\n"));
msdk_printf(MSDK_STRING("                                  dstx=<X coordinate of input video located in the output (def: 0)>\n"));
msdk_printf(MSDK_STRING("                                  dsty=<Y coordinate of input video located in the output (def: 0)>\n"));
msdk_printf(MSDK_STRING("                                  dstw=<width of input video located in the output (def: width)>\n"));
msdk_printf(MSDK_STRING("                                  dsth=<height of input video located in the output (def: height)>\n\n"));
msdk_printf(MSDK_STRING("                                  stream=<video file name>\n"));
msdk_printf(MSDK_STRING("                                  width=<input video width>\n"));
msdk_printf(MSDK_STRING("                                  GlobalAlphaEnable=1\n"));
msdk_printf(MSDK_STRING("                                  GlobalAlpha=<Alpha value>\n"));
msdk_printf(MSDK_STRING("                                  LumaKeyEnable=1\n"));
msdk_printf(MSDK_STRING("                                  LumaKeyMin=<Luma key min value>\n"));
msdk_printf(MSDK_STRING("                                  LumaKeyMax=<Luma key max value>\n"));
msdk_printf(MSDK_STRING("                                  ...\n"));
msdk_printf(MSDK_STRING("                                  The parameters file may contain up to 64 streams.\n\n"));
msdk_printf(MSDK_STRING("                                  For example:\n"));
msdk_printf(MSDK_STRING("                                  stream=input_720x480.yuv\n"));
msdk_printf(MSDK_STRING("                                  width=720\n"));
msdk_printf(MSDK_STRING("                                  height=480\n"));
msdk_printf(MSDK_STRING("                                  cropx=0\n"));
msdk_printf(MSDK_STRING("                                  cropy=0\n"));
msdk_printf(MSDK_STRING("                                  cropw=720\n"));
msdk_printf(MSDK_STRING("                                  croph=480\n"));
msdk_printf(MSDK_STRING("                                  dstx=0\n"));
msdk_printf(MSDK_STRING("                                  dsty=0\n"));
msdk_printf(MSDK_STRING("                                  dstw=720\n"));
msdk_printf(MSDK_STRING("                                  dsth=480\n\n"));
msdk_printf(MSDK_STRING("                                  stream=input_480x320.yuv\n"));
msdk_printf(MSDK_STRING("                                  width=480\n"));
msdk_printf(MSDK_STRING("                                  height=320\n"));
msdk_printf(MSDK_STRING("                                  cropx=0\n"));
msdk_printf(MSDK_STRING("                                  cropy=0\n"));
msdk_printf(MSDK_STRING("                                  cropw=480\n"));
msdk_printf(MSDK_STRING("                                  croph=320\n"));
msdk_printf(MSDK_STRING("                                  dstx=100\n"));
msdk_printf(MSDK_STRING("                                  dsty=100\n"));
msdk_printf(MSDK_STRING("                                  dstw=320\n"));
msdk_printf(MSDK_STRING("                                  dsth=240\n"));
msdk_printf(MSDK_STRING("                                  GlobalAlphaEnable=1\n"));
msdk_printf(MSDK_STRING("                                  GlobalAlpha=128\n"));
msdk_printf(MSDK_STRING("                                  LumaKeyEnable=1\n"));
msdk_printf(MSDK_STRING("                                  LumaKeyMin=250\n"));
msdk_printf(MSDK_STRING("                                  LumaKeyMax=255\n"));
msdk_printf(MSDK_STRING("   [-cf_disable]                  disable colorfill\n"));

msdk_printf(MSDK_STRING("   Video Enhancement Algorithms\n"));

msdk_printf(MSDK_STRING("   [-di_mode (mode)] - set type of deinterlace algorithm\n"));
msdk_printf(MSDK_STRING("                        12 - advanced with Scene Change Detection (SCD) \n"));
msdk_printf(MSDK_STRING("                        8 - reverse telecine for a selected telecine pattern (use -tc_pattern). For PTIR plug-in\n"));
msdk_printf(MSDK_STRING("                        2 - advanced or motion adaptive (default)\n"));
msdk_printf(MSDK_STRING("                        1 - simple or BOB\n\n"));

msdk_printf(MSDK_STRING("   [-deinterlace (type)] - enable deinterlace algorithm (alternative way: -spic 0 -dpic 1) \n"));
msdk_printf(MSDK_STRING("                         type is tff (default) or bff \n"));

msdk_printf(MSDK_STRING("   [-rotate (angle)]   - enable rotation. Supported angles: 0, 90, 180, 270.\n"));

msdk_printf(MSDK_STRING("   [-scaling_mode (mode)] - specify type of scaling to be used for resize\n"));
msdk_printf(MSDK_STRING("                            0 - default\n"));
msdk_printf(MSDK_STRING("                            1 - low power mode\n"));
msdk_printf(MSDK_STRING("                            2 - quality mode\n\n"));

#if MFX_VERSION >= 1033
msdk_printf(MSDK_STRING("   [-interpolation_method (method)] - specify interpolation method to be used for resize\n"));
msdk_printf(MSDK_STRING("                                      0 - default\n"));
msdk_printf(MSDK_STRING("                                      1 - nearest neighbor\n"));
msdk_printf(MSDK_STRING("                                      2 - bilinear\n"));
msdk_printf(MSDK_STRING("                                      3 - advanced\n\n"));
#endif

msdk_printf(MSDK_STRING("   [-denoise (level)]  - enable denoise algorithm. Level is optional \n"));
msdk_printf(MSDK_STRING("                         range of  noise level is [0, 100]\n"));
#if MFX_VERSION >= 1025
msdk_printf(MSDK_STRING("   [-chroma_siting (vmode hmode)] - specify chroma siting mode for VPP color conversion, allowed values: vtop|vcen|vbot hleft|hcen\n"));
#endif
#ifdef ENABLE_MCTF
#if !defined ENABLE_MCTF_EXT
msdk_printf(MSDK_STRING("  -mctf [Strength]\n"));
msdk_printf(MSDK_STRING("        Strength is an optional value;  it is in range [0...20]\n"));
msdk_printf(MSDK_STRING("        value 0 makes MCTF operates in auto mode;\n"));
msdk_printf(MSDK_STRING("        values [1...20] makes MCTF operates with fixed-strength mode;\n"));
msdk_printf(MSDK_STRING("        In fixed-strength mode, MCTF strength can be adjusted at framelevel;\n"));
msdk_printf(MSDK_STRING("        If no Strength is given, MCTF operates in auto mode.\n"));
#else
msdk_printf(MSDK_STRING("  -mctf MctfMode:BitsPerPixel:Strength:ME:Overlap:DB\n"));
msdk_printf(MSDK_STRING("        every parameter may be missed; in this case default value is used.\n"));
msdk_printf(MSDK_STRING("        MctfMode: 0 - spatial filter\n"));
msdk_printf(MSDK_STRING("        MctfMode: 1- temporal filtering, 1 backward reference\n"));
msdk_printf(MSDK_STRING("        MctfMode: 2- temporal filtering, 1 backward & 1 forward reference\n"));
msdk_printf(MSDK_STRING("        MctfMode: 3- temporal filtering, 2 backward & 2 forward references\n"));
msdk_printf(MSDK_STRING("        MctfMode:  other values: force default mode to be used\n"));
msdk_printf(MSDK_STRING("        BitsPerPixel: float, valid range [0...12.0]; if exists, is used for automatic filter strength adaptation. Default is 0.0\n"));
msdk_printf(MSDK_STRING("        Strength: integer, [0...20]. Default value is 0.\n"));
msdk_printf(MSDK_STRING("        ME: Motion Estimation precision; 0 - integer ME (default); 1 - quater-pel ME\n"));
msdk_printf(MSDK_STRING("        Overlap: 0 - do not apply overlap ME (default); 1 - to apply overlap ME\n"));
msdk_printf(MSDK_STRING("        DB: 0 - do not apply deblock Filter (default); 1 - to apply Deblock Filter\n"));
#endif //ENABLE_MCTF_EXT
#endif //ENABLE_MCTF
msdk_printf(MSDK_STRING("   [-detail  (level)]  - enable detail enhancement algorithm. Level is optional \n"));
msdk_printf(MSDK_STRING("                         range of detail level is [0, 100]\n\n"));
msdk_printf(MSDK_STRING("   [-pa_hue  hue]        - procamp hue property.         range [-180.0, 180.0] (def: 0.0)\n"));
msdk_printf(MSDK_STRING("   [-pa_sat  saturation] - procamp satursation property. range [   0.0,  10.0] (def: 1.0)\n"));
msdk_printf(MSDK_STRING("   [-pa_con  contrast]   - procamp contrast property.    range [   0.0,  10.0] (def: 1.0)\n"));
msdk_printf(MSDK_STRING("   [-pa_bri  brightness] - procamp brightness property.  range [-100.0, 100.0] (def: 0.0)\n\n"));
#ifdef ENABLE_VPP_RUNTIME_HSBC
msdk_printf(MSDK_STRING("   [-rt_hue  num_frames hue1 hue2] - enable per-frame hue adjustment in run-time without the whole video processing pipeline reinitialization.\n"));
msdk_printf(MSDK_STRING("             num_frames - a number of frames after which hue is changed either from hue1 to hue2 or from hue2 to hue1. \n"));
msdk_printf(MSDK_STRING("                          The first num_frames frames are initialized to hue1.\n"));
msdk_printf(MSDK_STRING("             hue1 - the first hue value in range [-180.0, 180.0] (def: 0.0)\n"));
msdk_printf(MSDK_STRING("             hue2 - the second hue value in range [-180.0, 180.0] (def: 0.0)\n\n"));
msdk_printf(MSDK_STRING("   [-rt_sat  num_frames sat1 sat2] - enable per-frame saturation adjustment in run-time without the whole video processing pipeline reinitialization.\n"));
msdk_printf(MSDK_STRING("             num_frames - a number of frames after which saturation is changed either from sat1 to sat2 or from sat2 to sat1. \n"));
msdk_printf(MSDK_STRING("                          The first num_frames frames are initialized to sat1.\n"));
msdk_printf(MSDK_STRING("             sat1 - the first saturation value in range [0.0, 10.0] (def: 1.0)\n"));
msdk_printf(MSDK_STRING("             sat2 - the second saturation value in range [0.0, 10.0] (def: 1.0)\n\n"));
msdk_printf(MSDK_STRING("   [-rt_con  num_frames con1 con2] - enable per-frame contrast adjustment in run-time without the whole video processing pipeline reinitialization.\n"));
msdk_printf(MSDK_STRING("             num_frames - a number of frames after which contrast is changed either from con1 to con2 or from con2 to con1. \n"));
msdk_printf(MSDK_STRING("                          The first num_frames frames are initialized to con1.\n"));
msdk_printf(MSDK_STRING("             con1 - the first contrast value in range [0.0, 10.0] (def: 1.0)\n"));
msdk_printf(MSDK_STRING("             con2 - the second contrast value in range [0.0, 10.0] (def: 1.0)\n\n"));
msdk_printf(MSDK_STRING("   [-rt_bri  num_frames bri1 bri2] - enable per-frame brightness adjustment in run-time without the whole video processing pipeline reinitialization.\n"));
msdk_printf(MSDK_STRING("             num_frames - a number of frames after which brightness is changed either from bri1 to bri2 or from bri2 to bri1. \n"));
msdk_printf(MSDK_STRING("                          The first num_frames frames are initialized to bri1.\n"));
msdk_printf(MSDK_STRING("             bri1 - the first brightness value in range [-100.0, 100.0] (def: 0.0)\n"));
msdk_printf(MSDK_STRING("             bri2 - the second brightness value in range [-100.0, 100.0] (def: 0.0)\n\n"));
#endif
msdk_printf(MSDK_STRING("   [-gamut:compression]  - enable gamut compression algorithm (xvYCC->sRGB) \n"));
msdk_printf(MSDK_STRING("   [-gamut:bt709]        - enable BT.709 matrix transform (RGB->YUV conversion)(def: BT.601)\n\n"));
msdk_printf(MSDK_STRING("   [-frc:advanced]       - enable advanced FRC algorithm (based on PTS) \n"));
msdk_printf(MSDK_STRING("   [-frc:interp]         - enable FRC based on frame interpolation algorithm\n\n"));

msdk_printf(MSDK_STRING("   [-tcc:red]            - enable color saturation algorithm (R component) \n"));
msdk_printf(MSDK_STRING("   [-tcc:green]          - enable color saturation algorithm (G component)\n"));
msdk_printf(MSDK_STRING("   [-tcc:blue]           - enable color saturation algorithm (B component)\n"));
msdk_printf(MSDK_STRING("   [-tcc:cyan]           - enable color saturation algorithm (C component)\n"));
msdk_printf(MSDK_STRING("   [-tcc:magenta]        - enable color saturation algorithm (M component)\n"));
msdk_printf(MSDK_STRING("   [-tcc:yellow]         - enable color saturation algorithm (Y component)\n\n"));

msdk_printf(MSDK_STRING("   [-ace]                - enable auto contrast enhancement algorithm \n\n"));
msdk_printf(MSDK_STRING("   [-ste (level)]        - enable Skin Tone Enhancement algorithm.  Level is optional \n"));
msdk_printf(MSDK_STRING("                           range of ste level is [0, 9] (def: 4)\n\n"));
msdk_printf(MSDK_STRING("   [-istab (mode)]       - enable Image Stabilization algorithm.  Mode is optional \n"));
msdk_printf(MSDK_STRING("                           mode of istab can be [1, 2] (def: 2)\n"));
msdk_printf(MSDK_STRING("                           where: 1 means upscale mode, 2 means croppping mode\n"));
msdk_printf(MSDK_STRING("   [-view:count value]   - enable Multi View preprocessing. range of views [1, 1024] (def: 1)\n\n"));
msdk_printf(MSDK_STRING("                           id-layerId, width/height-resolution \n\n"));
msdk_printf(MSDK_STRING("   [-ssitm (id)]         - specify YUV<->RGB transfer matrix for input surface.\n"));
msdk_printf(MSDK_STRING("   [-dsitm (id)]         - specify YUV<->RGB transfer matrix for output surface.\n"));
msdk_printf(MSDK_STRING("   [-ssinr (id)]         - specify YUV nominal range for input surface.\n"));
msdk_printf(MSDK_STRING("   [-dsinr (id)]         - specify YUV nominal range for output surface.\n\n"));
msdk_printf(MSDK_STRING("   [-mirror (mode)]      - mirror image using specified mode.\n"));

msdk_printf(MSDK_STRING("   [-n frames] - number of frames to VPP process\n\n"));

msdk_printf(MSDK_STRING("   [-iopattern IN/OUT surface type] -  IN/OUT surface type: sys_to_sys, sys_to_d3d, d3d_to_sys, d3d_to_d3d    (def: sys_to_sys)\n"));
msdk_printf(MSDK_STRING("   [-async n] - maximum number of asynchronious tasks. def: -async 1 \n"));
msdk_printf(MSDK_STRING("   [-perf_opt n m] - n: number of prefetech frames. m : number of passes. In performance mode app preallocates bufer and load first n frames,  def: no performace 1 \n"));
msdk_printf(MSDK_STRING("   [-pts_check] - checking of time stampls. Default is OFF \n"));
msdk_printf(MSDK_STRING("   [-pts_jump ] - checking of time stamps jumps. Jump for random value since 13-th frame. Also, you can change input frame rate (via pts). Default frame_rate = sf \n"));
msdk_printf(MSDK_STRING("   [-pts_fr ]   - input frame rate which used for pts. Default frame_rate = sf \n"));
msdk_printf(MSDK_STRING("   [-pts_advanced]   - enable FRC checking mode based on PTS \n"));
msdk_printf(MSDK_STRING("   [-pf file for performance data] -  file to save performance data. Default is off \n\n\n"));

msdk_printf(MSDK_STRING("   [-roi_check mode seed1 seed2] - checking of ROI processing. Default is OFF \n"));
msdk_printf(MSDK_STRING("               mode - usage model of cropping\n"));
msdk_printf(MSDK_STRING("                      var_to_fix - variable input ROI and fixed output ROI\n"));
msdk_printf(MSDK_STRING("                      fix_to_var - fixed input ROI and variable output ROI\n"));
msdk_printf(MSDK_STRING("                      var_to_var - variable input ROI and variable output ROI\n"));
msdk_printf(MSDK_STRING("               seed1 - seed for init of rand generator for src\n"));
msdk_printf(MSDK_STRING("               seed2 - seed for init of rand generator for dst\n"));
msdk_printf(MSDK_STRING("                       range of seed [1, 65535]. 0 reserved for random init\n\n"));

msdk_printf(MSDK_STRING("   [-tc_pattern (pattern)] - set telecine pattern\n"));
msdk_printf(MSDK_STRING("                        4 - provide a position inside a sequence of 5 frames where the artifacts starts. Use to -tc_pos to provide position\n"));
msdk_printf(MSDK_STRING("                        3 - 4:1 pattern\n"));
msdk_printf(MSDK_STRING("                        2 - frame repeat pattern\n"));
msdk_printf(MSDK_STRING("                        1 - 2:3:3:2 pattern\n"));
msdk_printf(MSDK_STRING("                        0 - 3:2 pattern\n\n"));

msdk_printf(MSDK_STRING("   [-tc_pos (position)] - Position inside a telecine sequence of 5 frames where the artifacts starts - Value [0 - 4]\n\n"));

msdk_printf(MSDK_STRING("   [-reset_start (frame number)] - after reaching this frame, encoder will be reset with new parameters, followed after this command and before -reset_end \n"));
msdk_printf(MSDK_STRING("   [-reset_end]                  - specifies end of reset related options \n\n"));

msdk_printf(MSDK_STRING("\n"));

msdk_printf(MSDK_STRING("Usage2: %s -sw 352 -sh 144 -scc rgb3 -dw 320 -dh 240 -dcc nv12 -denoise 32 -iopattern d3d_to_d3d -i in.rgb -o out.yuv -roi_check var_to_fix 7 7\n"), strAppName);

msdk_printf(MSDK_STRING("\n"));

} // void vppPrintHelp(msdk_char *strAppName, msdk_char *strErrorMessage)


mfxU16 GetPicStruct( mfxI8 picStruct )
{
 if ( 0 == picStruct )
    {
        return MFX_PICSTRUCT_FIELD_TFF;
    }
    else if( 2 == picStruct )
    {
        return MFX_PICSTRUCT_FIELD_BFF;
    }
    else if( 3 == picStruct )
    {
        return MFX_PICSTRUCT_FIELD_SINGLE;
    }
    else if( -1 == picStruct )
    {
        return MFX_PICSTRUCT_UNKNOWN;
    }
    else
    {
        return MFX_PICSTRUCT_PROGRESSIVE;
    }

} // mfxU16 GetPicStruct( mfxI8 picStruct )


mfxU32 Str2FourCC( msdk_char* strInput )
{
    mfxU32 fourcc = 0;//default

    if ( 0 == msdk_stricmp(strInput, MSDK_STRING("yv12")) )
    {
        fourcc = MFX_FOURCC_YV12;
    }
#if (MFX_VERSION >= 1028)
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("rgb565")) )
    {
        fourcc = MFX_FOURCC_RGB565;
    }
#endif
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("rgb3")) )
    {
        fourcc = MFX_FOURCC_RGB3;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("rgb4")) )
    {
        fourcc = MFX_FOURCC_RGB4;
    }
#if !(defined(_WIN32) || defined(_WIN64))
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("rgbp")) )
    {
        fourcc = MFX_FOURCC_RGBP;
    }
#endif
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("yuy2")) )
    {
        fourcc = MFX_FOURCC_YUY2;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("nv12")) )
    {
        fourcc = MFX_FOURCC_NV12;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("imc3")) )
    {
        fourcc = MFX_FOURCC_IMC3;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("yuv400")) )
    {
        fourcc = MFX_FOURCC_YUV400;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("yuv411")) )
    {
        fourcc = MFX_FOURCC_YUV411;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("yuv422h")) )
    {
        fourcc = MFX_FOURCC_YUV422H;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("yuv422v")) )
    {
        fourcc = MFX_FOURCC_YUV422V;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("yuv444")) )
    {
        fourcc = MFX_FOURCC_YUV444;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("p010")) )
    {
        fourcc = MFX_FOURCC_P010;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("p210")) )
    {
        fourcc = MFX_FOURCC_P210;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("nv16")) )
    {
        fourcc = MFX_FOURCC_NV16;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("a2rgb10")) )
    {
        fourcc = MFX_FOURCC_A2RGB10;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("uyvy")) )
    {
        fourcc = MFX_FOURCC_UYVY;
    }
#if (MFX_VERSION >= 1027)
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("y210")) )
    {
        fourcc = MFX_FOURCC_Y210;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("y410")) )
    {
        fourcc = MFX_FOURCC_Y410;
    }
#endif
#if (MFX_VERSION >= 1031)
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("p016")) )
    {
        fourcc = MFX_FOURCC_P016;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("y216")) )
    {
        fourcc = MFX_FOURCC_Y216;
    }
    else if ( 0 == msdk_stricmp(strInput, MSDK_STRING("y416")) )
    {
        fourcc = MFX_FOURCC_Y416;
    }
#endif
    else if (0 == msdk_stricmp(strInput, MSDK_STRING("i420")))
    {
        fourcc = MFX_FOURCC_I420;
    } else if (0 == msdk_stricmp(strInput, MSDK_STRING("ayuv"))) {
        fourcc = MFX_FOURCC_AYUV;
    }

    return fourcc;

} // mfxU32 Str2FourCC( msdk_char* strInput )


eROIMode Str2ROIMode( msdk_char* strInput )
{
    eROIMode mode;

    if ( 0 == msdk_strcmp(strInput, MSDK_STRING("var_to_fix")) )
    {
        mode = ROI_VAR_TO_FIX;
    }
    else if ( 0 == msdk_strcmp(strInput, MSDK_STRING("var_to_var")) )
    {
        mode = ROI_VAR_TO_VAR;
    }
    else if ( 0 == msdk_strcmp(strInput, MSDK_STRING("fix_to_var")) )
    {
        mode = ROI_FIX_TO_VAR;
    }
    else
    {
        mode = ROI_FIX_TO_FIX; // default mode
    }

    return mode;

} // eROIMode Str2ROIMode( msdk_char* strInput )


static mfxU16 Str2IOpattern( msdk_char* strInput )
{
    mfxU16 IOPattern = 0;

    if ( 0 == msdk_strcmp(strInput, MSDK_STRING("d3d_to_d3d")) )
    {
        IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY|MFX_IOPATTERN_OUT_VIDEO_MEMORY;
    }
    else if ( 0 == msdk_strcmp(strInput, MSDK_STRING("d3d_to_sys")) )
    {
        IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY|MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
    }
    else if ( 0 == msdk_strcmp(strInput, MSDK_STRING("sys_to_d3d")) )
    {
        IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY|MFX_IOPATTERN_OUT_VIDEO_MEMORY;
    }
    else if ( 0 == msdk_strcmp(strInput, MSDK_STRING("sys_to_sys")) )
    {
        IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY|MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
    }
    return IOPattern;

} // static mfxU16 Str2IOpattern( msdk_char* strInput )

#ifdef ENABLE_MCTF
// returns a pointer to start of argument with a number argn;
// if failes to find argn, returns NULL
msdk_char* ParseArgn(msdk_char* pIn, mfxU32 argn, msdk_char separator) {

    msdk_char* pstr = pIn;
    if (!argn)
        return pIn;
    else {
        for (mfxU32 n = 0; n != argn; ++n) {
            while (separator != *pstr && msdk_char('\0') != *pstr)
                ++pstr;
            if (msdk_char('\0') == *pstr)
                return NULL;
            else
                ++pstr;
        }
        return pstr;
    }
};

template <typename T>
void ArgConvert(msdk_char* pIn, mfxU32 argn, const msdk_char* pattern, T* pArg, T ArgDefault, mfxU32& NumOfGoodConverts) {
    msdk_char* pargs = ParseArgn(pIn, argn, msdk_char(':'));
    if (pargs) {
        if (!msdk_sscanf(pargs, pattern, pArg))
            *pArg = ArgDefault;
        else
            ++NumOfGoodConverts;
    };
}

void ParseMCTFParams(msdk_char* strInput[], mfxU8 nArgNum, mfxU8& curArg, sInputParams* pParams, mfxU32 paramID)
{
    mfxU8& i = curArg;
    if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-mctf")))
    {
        pParams->mctfParam[paramID].mode = VPP_FILTER_ENABLED_DEFAULT;
        pParams->mctfParam[paramID].params.FilterStrength = 0;
#if defined ENABLE_MCTF_EXT
        pParams->mctfParam[paramID].params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_2REF; // default
        pParams->mctfParam[paramID].params.BitsPerPixelx100k= 0;
        pParams->mctfParam[paramID].params.Deblocking = MFX_CODINGOPTION_OFF;
        pParams->mctfParam[paramID].params.Overlap = MFX_CODINGOPTION_OFF;
        pParams->mctfParam[paramID].params.MVPrecision = MFX_MVPRECISION_INTEGER;
#endif


        if (i + 1 < nArgNum)
        {
            mfxU16 _strength(0);
            mfxU32 strength_idx = 0;
            mfxU32 ParsedArgsNumber = 0;

            //the order of arguments is:
            //Strength:ReferencesMode:BitsPerPixel:ME:Overlap:DB

            ArgConvert(strInput[i + 1], strength_idx, MSDK_STRING("%hd:%*c"), &_strength, _strength, ParsedArgsNumber);
#if defined ENABLE_MCTF_EXT
            mfxU16 _refnum(MFX_MCTF_TEMPORAL_MODE_2REF);
            mfxF64 _bitsperpixel(0.0);
            mfxU16 _me_precision(0);
            mfxU16 _overlap(0);
            mfxU16 _deblock(0);

            ArgConvert(strInput[i + 1], 1, MSDK_STRING("%hd:%*c"), &_refnum, _refnum, ParsedArgsNumber);
            ArgConvert(strInput[i + 1], 2, MSDK_STRING("%lf:%*c"), &_bitsperpixel, _bitsperpixel, ParsedArgsNumber);
            ArgConvert(strInput[i + 1], 3, MSDK_STRING("%hd:%*c"), &_me_precision, _me_precision, ParsedArgsNumber);
            ArgConvert(strInput[i + 1], 4, MSDK_STRING("%hd:%*c"), &_overlap, _overlap, ParsedArgsNumber);
            ArgConvert(strInput[i + 1], 5, MSDK_STRING("%hd:%*c"), &_deblock, _deblock, ParsedArgsNumber);
#endif
            if (ParsedArgsNumber > 0)
            {
                pParams->mctfParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
            }
            else
            {
                pParams->mctfParam[paramID].mode = VPP_FILTER_ENABLED_DEFAULT;
                msdk_printf(MSDK_STRING("MCTF works in default mode; no parameters are passed.\n"));
            }
            pParams->mctfParam[paramID].params.FilterStrength = _strength;
#if defined ENABLE_MCTF_EXT
            pParams->mctfParam[paramID].params.BitsPerPixelx100k = mfxU32(_bitsperpixel * MCTF_BITRATE_MULTIPLIER);
            switch (_refnum) {
            case 0:
                pParams->mctfParam[paramID].params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_SPATIAL;
                break;
            case 1:
                pParams->mctfParam[paramID].params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_1REF;
                break;
            case 2:
                pParams->mctfParam[paramID].params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_2REF;
                break;
            case 3:
                pParams->mctfParam[paramID].params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_4REF;
                break;
            default:
                pParams->mctfParam[paramID].params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_UNKNOWN;
            };
            switch (_deblock) {
            case 0:
                pParams->mctfParam[paramID].params.Deblocking = MFX_CODINGOPTION_OFF;
                break;
            case 1:
                pParams->mctfParam[paramID].params.Deblocking = MFX_CODINGOPTION_ON;
                break;
            default:
                pParams->mctfParam[paramID].params.Deblocking = MFX_CODINGOPTION_UNKNOWN;
            };
            switch (_overlap) {
            case 0:
                pParams->mctfParam[paramID].params.Overlap = MFX_CODINGOPTION_OFF;
                break;
            case 1:
                pParams->mctfParam[paramID].params.Overlap = MFX_CODINGOPTION_ON;
                break;
            default:
                pParams->mctfParam[paramID].params.Overlap = MFX_CODINGOPTION_UNKNOWN;
            };
            switch (_me_precision) {
            case 0:
                pParams->mctfParam[paramID].params.MVPrecision = MFX_MVPRECISION_INTEGER;
                break;
            case 1:
                pParams->mctfParam[paramID].params.MVPrecision = MFX_MVPRECISION_QUARTERPEL;
                break;
            default:
                pParams->mctfParam[paramID].params.MVPrecision = MFX_MVPRECISION_UNKNOWN;
            };
#endif
            if(ParsedArgsNumber)
                i++;
        }
        else
        {
            msdk_printf(MSDK_STRING("MCTF works in default mode; no parameters are passed.\n"));
        }
    }
}
#endif


mfxStatus vppParseResetPar(msdk_char* strInput[], mfxU8 nArgNum, mfxU8& curArg, sInputParams* pParams, mfxU32 paramID, sFiltersParam* pDefaultFiltersParam)
{
    MSDK_CHECK_POINTER(pParams,  MFX_ERR_NULL_PTR);
    MSDK_CHECK_POINTER(strInput, MFX_ERR_NULL_PTR);

    sOwnFrameInfo info = pParams->frameInfoIn.back();
    pParams->frameInfoIn.push_back(info);
    info = pParams->frameInfoOut.back();
    pParams->frameInfoOut.push_back(info);

    pParams->deinterlaceParam.push_back(    *pDefaultFiltersParam->pDIParam            );
    pParams->denoiseParam.push_back(        *pDefaultFiltersParam->pDenoiseParam       );
#ifdef ENABLE_MCTF
    pParams->mctfParam.push_back(           *pDefaultFiltersParam->pMctfParam          );
#endif
    pParams->detailParam.push_back(         *pDefaultFiltersParam->pDetailParam        );
    pParams->procampParam.push_back(        *pDefaultFiltersParam->pProcAmpParam       );
    pParams->frcParam.push_back(            *pDefaultFiltersParam->pFRCParam           );
    pParams->multiViewParam.push_back(      *pDefaultFiltersParam->pMultiViewParam     );
    pParams->gamutParam.push_back(          *pDefaultFiltersParam->pGamutParam         );
    pParams->tccParam.push_back(            *pDefaultFiltersParam->pClrSaturationParam );
    pParams->aceParam.push_back(            *pDefaultFiltersParam->pContrastParam      );
    pParams->steParam.push_back(            *pDefaultFiltersParam->pSkinParam          );
    pParams->istabParam.push_back(          *pDefaultFiltersParam->pImgStabParam       );
    pParams->videoSignalInfoParam.push_back(*pDefaultFiltersParam->pVideoSignalInfo    );
    pParams->mirroringParam.push_back(      *pDefaultFiltersParam->pMirroringParam     );
    pParams->rotate.push_back(               0                                         );
    pParams->colorfillParam.push_back(      *pDefaultFiltersParam->pColorfillParam     );

    mfxU32 readData;
    mfxU32 ioStatus;

    for (mfxU8& i = curArg; i < nArgNum; i++ )
    {
        MSDK_CHECK_POINTER(strInput[i], MFX_ERR_NULL_PTR);
        {
            if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-o")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;

                pParams->strDstFiles.push_back(strInput[i]);
                pParams->isOutput = true;
            }
            //-----------------------------------------------------------------------------------
            //                   Video Enhancement Algorithms
            //-----------------------------------------------------------------------------------
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-ssinr")) )
            {
                VAL_CHECK(1 + i == nArgNum);

                pParams->videoSignalInfoParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;

                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->videoSignalInfoParam[paramID].In.NominalRange);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-dsinr")) )
            {
                VAL_CHECK(1 + i == nArgNum);

                pParams->videoSignalInfoParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;

                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->videoSignalInfoParam[paramID].Out.NominalRange);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-ssitm")) )
            {
                VAL_CHECK(1 + i == nArgNum);

                pParams->videoSignalInfoParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;

                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->videoSignalInfoParam[paramID].In.TransferMatrix);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-dsitm")) )
            {
                VAL_CHECK(1 + i == nArgNum);

                pParams->videoSignalInfoParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;

                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->videoSignalInfoParam[paramID].Out.TransferMatrix);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-mirror")) )
            {
                VAL_CHECK(1 + i == nArgNum);

                pParams->mirroringParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;

                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->mirroringParam[paramID].Type);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-sw")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoIn.back().nWidth);
            }
            else if ( 0 == msdk_stricmp(strInput[i], MSDK_STRING("-dw")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoOut.back().nWidth);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-sh")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoIn.back().nHeight);
            }
            else if ( 0 == msdk_stricmp(strInput[i], MSDK_STRING("-dh")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoOut.back().nHeight);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-denoise")))
            {
                pParams->denoiseParam[paramID].mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->denoiseParam[paramID].factor = (mfxU16)readData;
                        pParams->denoiseParam[paramID].mode   = VPP_FILTER_ENABLED_CONFIGURED;
                        i++;
                    }
                }
            }
#ifdef ENABLE_MCTF
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-mctf")))
            {
                ParseMCTFParams(strInput, nArgNum, i, pParams, paramID);
            }

#endif
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-di_mode")))
            {
                pParams->deinterlaceParam[paramID].mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->deinterlaceParam[paramID].algorithm = (mfxU16)readData;
                        pParams->deinterlaceParam[paramID].mode   = VPP_FILTER_ENABLED_CONFIGURED;
                        i++;
                    }
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tc_pattern")))
            {
                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->deinterlaceParam[paramID].tc_pattern   = (mfxU16)readData;
                        i++;
                    }
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tc_pos")))
            {
                //pParams->deinterlaceParam.mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->deinterlaceParam[paramID].tc_pos   = (mfxU16)readData;
                        i++;
                    }
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-detail")))
            {
                pParams->detailParam[paramID].mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->detailParam[paramID].factor = (mfxU16)readData;
                        pParams->detailParam[paramID].mode   = VPP_FILTER_ENABLED_CONFIGURED;
                        i++;
                    }
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-rotate")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->rotate[paramID]);
            }
            // different modes of MFX FRC
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-frc:advanced")))
            {
                pParams->frcParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                pParams->frcParam[paramID].algorithm = MFX_FRCALGM_DISTRIBUTED_TIMESTAMP;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-frc:interp")))
            {
                pParams->frcParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                pParams->frcParam[paramID].algorithm = MFX_FRCALGM_FRAME_INTERPOLATION;
            }
            //---------------------------------------------
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pa_hue")))
            {
                pParams->procampParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->procampParam[paramID].hue);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pa_bri")))
            {
                pParams->procampParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->procampParam[paramID].brightness);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pa_con")))
            {
                pParams->procampParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->procampParam[paramID].contrast);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pa_sat")))
            {
                pParams->procampParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->procampParam[paramID].saturation);
            }
#ifdef ENABLE_VPP_RUNTIME_HSBC
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-rt_hue")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%u"), &pParams->rtHue.interval);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtHue.value1);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtHue.value2);
                pParams->rtHue.isEnabled = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-rt_bri")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%u"), &pParams->rtBrightness.interval);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtBrightness.value1);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtBrightness.value2);
                pParams->rtBrightness.isEnabled = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-rt_con")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%u"), &pParams->rtContrast.interval);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtContrast.value1);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtContrast.value2);
                pParams->rtContrast.isEnabled = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-rt_sat")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%u"), &pParams->rtSaturation.interval);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtSaturation.value1);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtSaturation.value2);
                pParams->rtSaturation.isEnabled = true;
            }
#endif
            //MSDK 3.0
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-gamut:compression")))
            {
                pParams->gamutParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-gamut:bt709")))
            {
                pParams->gamutParam[paramID].bBT709 = true;
            }
            else if( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-view:count")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;

                mfxU16 viewCount;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &viewCount);
                if( viewCount > 1 )
                {
                    pParams->multiViewParam[paramID].viewCount = (mfxU16)viewCount;
                    pParams->multiViewParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                }
            }
            //---------------------------------------------
            // MSDK API 1.5
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-istab")))
            {
                pParams->istabParam[paramID].mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->istabParam[paramID].istabMode = (mfxU8)readData;
                        pParams->istabParam[paramID].mode    = VPP_FILTER_ENABLED_CONFIGURED;
                        i++;

                        if( pParams->istabParam[paramID].istabMode != 1 && pParams->istabParam[paramID].istabMode != 2 )
                        {
                            vppPrintHelp(strInput[0], MSDK_STRING("Invalid IStab configuration"));
                            return MFX_ERR_UNSUPPORTED;
                        }
                    }
                }
            }
            //---------------------------------------------
            // IECP
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-ace")))
            {
                pParams->aceParam[paramID].mode = VPP_FILTER_ENABLED_DEFAULT;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-ste")))
            {
                pParams->steParam[paramID].mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->steParam[paramID].SkinToneFactor = (mfxU8)readData;
                        pParams->steParam[paramID].mode           = VPP_FILTER_ENABLED_CONFIGURED;
                        i++;
                    }
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:red")))
            {
                pParams->tccParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[paramID].Red));
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:green")))
            {
                pParams->tccParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[paramID].Green));
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:blue")))
            {
                pParams->tccParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[paramID].Blue));
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:magenta")))
            {
                pParams->tccParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[paramID].Magenta));
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:yellow")))
            {
                pParams->tccParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[paramID].Yellow));
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:cyan")))
            {
                pParams->tccParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[paramID].Cyan));
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-reset_end")))
            {
                break;
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-cf_disable")) )
            {
                pParams->colorfillParam[paramID].mode = VPP_FILTER_ENABLED_CONFIGURED;
                pParams->colorfillParam[paramID].Enable = MFX_CODINGOPTION_OFF;
            }
            else
            {
                msdk_printf(MSDK_STRING("Unknow reset option: %s\n"), strInput[i]);

                return MFX_ERR_UNKNOWN;
            }
        }
    }

    return MFX_ERR_NONE;

} // mfxStatus vppParseResetPar( ... )

void AdjustBitDepth (sInputParams & params)
{
    if (params.frameInfoIn[0].BitDepthLuma != 0 || params.frameInfoIn[0].BitDepthChroma != 0)
    {
        if (params.frameInfoIn[0].BitDepthLuma == 0)
        {
            params.frameInfoIn[0].BitDepthLuma = params.frameInfoIn[0].BitDepthChroma;
            msdk_printf(MSDK_STRING("Warning: input BitDepthLuma was defaulted to value which was set to BitDepthChroma (%d)."), params.frameInfoIn[0].BitDepthLuma);
        }

        if (params.frameInfoIn[0].BitDepthChroma == 0)
        {
            params.frameInfoIn[0].BitDepthChroma = params.frameInfoIn[0].BitDepthLuma;
            msdk_printf(MSDK_STRING("Warning: input BitDepthChroma was defaulted to value which was set to BitDepthLuma (%d)."), params.frameInfoIn[0].BitDepthChroma);
        }
    }

    if (params.frameInfoOut[0].BitDepthLuma != 0 || params.frameInfoOut[0].BitDepthChroma != 0)
    {
        if (params.frameInfoOut[0].BitDepthLuma == 0)
        {
            params.frameInfoOut[0].BitDepthLuma = params.frameInfoOut[0].BitDepthChroma;
            msdk_printf(MSDK_STRING("Warning: output BitDepthLuma was defaulted to value which was set to BitDepthChroma (%d)."), params.frameInfoOut[0].BitDepthLuma);
        }

        if (params.frameInfoOut[0].BitDepthChroma == 0)
        {
            params.frameInfoOut[0].BitDepthChroma = params.frameInfoOut[0].BitDepthLuma;
            msdk_printf(MSDK_STRING("Warning: output BitDepthChroma was defaulted to value which was set to BitDepthLuma (%d)."), params.frameInfoOut[0].BitDepthChroma);
        }
    }
}

mfxStatus vppParseInputString(msdk_char* strInput[], mfxU8 nArgNum, sInputParams* pParams, sFiltersParam* pDefaultFiltersParam)
{
    MSDK_CHECK_POINTER(pParams,  MFX_ERR_NULL_PTR);
    MSDK_CHECK_POINTER(strInput, MFX_ERR_NULL_PTR);

    mfxU32 readData;
    mfxU32 ioStatus;
    if (nArgNum < 4)
    {
        vppPrintHelp(strInput[0], MSDK_STRING("Not enough parameters"));

        return MFX_ERR_MORE_DATA;
    }

    pParams->frameInfoIn.back().CropX = 0;
    pParams->frameInfoIn.back().CropY = 0;
    pParams->frameInfoIn.back().CropW = NOT_INIT_VALUE;
    pParams->frameInfoIn.back().CropH = NOT_INIT_VALUE;
    // zeroize destination crops
    pParams->frameInfoOut.back().CropX = 0;
    pParams->frameInfoOut.back().CropY = 0;
    pParams->frameInfoOut.back().CropW = NOT_INIT_VALUE;
    pParams->frameInfoOut.back().CropH = NOT_INIT_VALUE;
    pParams->numStreams=1;

    for (mfxU8 i = 1; i < nArgNum; i++ )
    {
        MSDK_CHECK_POINTER(strInput[i], MFX_ERR_NULL_PTR);
        {
            if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-ssinr")) )
            {
                VAL_CHECK(1 + i == nArgNum);

                pParams->videoSignalInfoParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;

                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->videoSignalInfoParam[0].In.NominalRange);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-dsinr")) )
            {
                VAL_CHECK(1 + i == nArgNum);

                pParams->videoSignalInfoParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;

                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->videoSignalInfoParam[0].Out.NominalRange);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-ssitm")) )
            {
                VAL_CHECK(1 + i == nArgNum);

                pParams->videoSignalInfoParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;

                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->videoSignalInfoParam[0].In.TransferMatrix);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-dsitm")) )
            {
                VAL_CHECK(1 + i == nArgNum);

                pParams->videoSignalInfoParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;

                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->videoSignalInfoParam[0].Out.TransferMatrix);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-mirror")) )
            {
                VAL_CHECK(1 + i == nArgNum);

                pParams->mirroringParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;

                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->mirroringParam[0].Type);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-gpu_copy")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                pParams->bInitEx = true;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->GPUCopyValue);
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-sw")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoIn[0].nWidth);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-sh")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoIn[0].nHeight);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-scrX")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoIn[0].CropX);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-scrY")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoIn[0].CropY);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-scrW")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoIn[0].CropW);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-scrH")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoIn[0].CropH);
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-spic")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                mfxI16 tmp;
                msdk_sscanf(strInput[i], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&tmp));
                pParams->frameInfoIn[0].PicStruct = GetPicStruct(static_cast<mfxI8>(tmp));
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-sf")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->frameInfoIn[0].dFrameRate);
            }
            else if (0 == msdk_stricmp(strInput[i], MSDK_STRING("-dw")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoOut[0].nWidth);
            }
            else if (0 == msdk_stricmp(strInput[i], MSDK_STRING("-dh")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoOut[0].nHeight);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-dcrX")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoOut[0].CropX);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-dcrY")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoOut[0].CropY);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-dcrW")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoOut[0].CropW);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-dcrH")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoOut[0].CropH);
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-dpic")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                mfxI16 tmp;
                msdk_sscanf(strInput[i], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&tmp));
                pParams->frameInfoOut[0].PicStruct = GetPicStruct(static_cast<mfxI8>(tmp));
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-df")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->frameInfoOut[0].dFrameRate);
            }
            //-----------------------------------------------------------------------------------
            //                   Video Enhancement Algorithms
            //-----------------------------------------------------------------------------------
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-denoise")))
            {
                pParams->denoiseParam[0].mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->denoiseParam[0].factor = (mfxU16)readData;
                        pParams->denoiseParam[0].mode   = VPP_FILTER_ENABLED_CONFIGURED;
                        i++;
                    }
                }
            }
#ifdef ENABLE_MCTF
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-mctf")))
            {
                ParseMCTFParams(strInput, nArgNum, i, pParams, 0);
            }
#endif

            // aya: altenative and simple way to enable deinterlace
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-deinterlace")))
            {
                pParams->frameInfoOut[0].PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
                pParams->frameInfoIn[0].PicStruct  = MFX_PICSTRUCT_FIELD_TFF;

                if( i+1 < nArgNum )
                {
                    if(0 == msdk_strcmp(strInput[i+1], MSDK_STRING("bff")))
                    {
                        pParams->frameInfoOut[0].PicStruct = MFX_PICSTRUCT_FIELD_BFF;
                        i++;
                    }
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-di_mode")))
            {
                pParams->deinterlaceParam[0].mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->deinterlaceParam[0].algorithm = (mfxU16)readData;
                        pParams->deinterlaceParam[0].mode   = VPP_FILTER_ENABLED_CONFIGURED;
                        i++;
                    }
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tc_pattern")))
            {
                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->deinterlaceParam[0].tc_pattern   = (mfxU16)readData;
                        i++;
                    }
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tc_pos")))
            {
                //pParams->deinterlaceParam.mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->deinterlaceParam[0].tc_pos   = (mfxU16)readData;
                        i++;
                    }
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-detail")))
            {
                pParams->detailParam[0].mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->detailParam[0].factor = (mfxU16)readData;
                        pParams->detailParam[0].mode   = VPP_FILTER_ENABLED_CONFIGURED;
                        i++;
                    }
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-rotate")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->rotate[0]);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-scaling_mode")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                pParams->bScaling = true;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->scalingMode);
            }
#if MFX_VERSION >= 1033
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-interpolation_method")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                pParams->bScaling = true;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->interpolationMethod);
            }
#endif
#if MFX_VERSION >= 1025
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-chroma_siting")))
            {
                VAL_CHECK(2 + i == nArgNum);
                bool bVfound = false;
                bool bHfound = false;
                i++;
                for (int ii = 0; ii < 2; ii++)
                {
                    /* ChromaSiting */
                    if (msdk_strcmp(strInput[i + ii], MSDK_STRING("vtop")) == 0) { pParams->uChromaSiting |= MFX_CHROMA_SITING_VERTICAL_TOP; bVfound = true; }
                    else if (msdk_strcmp(strInput[i + ii], MSDK_STRING("vcen")) == 0) { pParams->uChromaSiting |= MFX_CHROMA_SITING_VERTICAL_CENTER; bVfound = true; }
                    else if (msdk_strcmp(strInput[i + ii], MSDK_STRING("vbot")) == 0) { pParams->uChromaSiting |= MFX_CHROMA_SITING_VERTICAL_BOTTOM; bVfound = true; }
                    else if (msdk_strcmp(strInput[i + ii], MSDK_STRING("hleft")) == 0) { pParams->uChromaSiting |= MFX_CHROMA_SITING_HORIZONTAL_LEFT; bHfound = true; }
                    else if (msdk_strcmp(strInput[i + ii], MSDK_STRING("hcen")) == 0) { pParams->uChromaSiting |= MFX_CHROMA_SITING_HORIZONTAL_CENTER; bHfound = true; }
                    else msdk_strcmp(MSDK_STRING("Unknown Chroma siting flag %s"), strInput[i + ii]);
                }
                pParams->bChromaSiting = bVfound && bHfound;
                if (!pParams->bChromaSiting)
                {
                    vppPrintHelp(strInput[0], MSDK_STRING("Invalid chroma siting flags\n"));
                    return MFX_ERR_UNSUPPORTED;
                }
                i++;
            }
#endif
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-composite")))
            {
                if( i+1 < nArgNum )
                {
                    if (ParseCompositionParfile(strInput[i+1], pParams) != MFX_ERR_NONE)
                    {
                        vppPrintHelp(strInput[0], MSDK_STRING("Parfile for -composite has invalid data or cannot be opened\n"));
                        return MFX_ERR_UNSUPPORTED;
                    }
                    pParams->compositionParam.mode = VPP_FILTER_ENABLED_CONFIGURED;
                    i++;
                }
            }
            // different modes of MFX FRC
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-frc:advanced")))
            {
                pParams->frcParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                pParams->frcParam[0].algorithm = MFX_FRCALGM_DISTRIBUTED_TIMESTAMP;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-frc:interp")))
            {
                pParams->frcParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                pParams->frcParam[0].algorithm = MFX_FRCALGM_FRAME_INTERPOLATION;
            }
            //---------------------------------------------
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pa_hue")))
            {
                pParams->procampParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->procampParam[0].hue);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pa_bri")))
            {
                pParams->procampParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->procampParam[0].brightness);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pa_con")))
            {
                pParams->procampParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->procampParam[0].contrast);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pa_sat")))
            {
                pParams->procampParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->procampParam[0].saturation);
            }
#ifdef ENABLE_VPP_RUNTIME_HSBC
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-rt_hue")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%u"), &pParams->rtHue.interval);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtHue.value1);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtHue.value2);
                pParams->rtHue.isEnabled = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-rt_bri")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%u"), &pParams->rtBrightness.interval);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtBrightness.value1);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtBrightness.value2);
                pParams->rtBrightness.isEnabled = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-rt_con")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%u"), &pParams->rtContrast.interval);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtContrast.value1);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtContrast.value2);
                pParams->rtContrast.isEnabled = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-rt_sat")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%u"), &pParams->rtSaturation.interval);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtSaturation.value1);
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->rtSaturation.value2);
                pParams->rtSaturation.isEnabled = true;
            }
#endif

            //MSDK 3.0
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-gamut:compression")))
            {
                pParams->gamutParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-gamut:bt709")))
            {
                pParams->gamutParam[0].bBT709 = true;
            }
            else if( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-view:count")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;

                mfxU16 viewCount;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &viewCount);
                if( viewCount > 1 )
                {
                    pParams->multiViewParam[0].viewCount = (mfxU16)viewCount;
                    pParams->multiViewParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                }
            }
            //---------------------------------------------
            // MSDK API 1.5
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-istab")))
            {
                pParams->istabParam[0].mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->istabParam[0].istabMode = (mfxU8)readData;
                        pParams->istabParam[0].mode    = VPP_FILTER_ENABLED_CONFIGURED;
                        i++;

                        if( pParams->istabParam[0].istabMode != 1 && pParams->istabParam[0].istabMode != 2 )
                        {
                            vppPrintHelp(strInput[0], MSDK_STRING("Invalid IStab configuration"));
                            return MFX_ERR_UNSUPPORTED;
                        }
                    }
                }
            }
            //---------------------------------------------
            // IECP
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-ace")))
            {
                pParams->aceParam[0].mode = VPP_FILTER_ENABLED_DEFAULT;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-ste")))
            {
                pParams->steParam[0].mode = VPP_FILTER_ENABLED_DEFAULT;

                if( i+1 < nArgNum )
                {
                    ioStatus = msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int *>(&readData));
                    if ( ioStatus > 0 )
                    {
                        pParams->steParam[0].SkinToneFactor = (mfxU8)readData;
                        pParams->steParam[0].mode           = VPP_FILTER_ENABLED_CONFIGURED;
                        i++;
                    }
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:red")))
            {
                pParams->tccParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[0].Red));
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:green")))
            {
                pParams->tccParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[0].Green));
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:blue")))
            {
                pParams->tccParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[0].Blue));
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:magenta")))
            {
                pParams->tccParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[0].Magenta));
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:yellow")))
            {
                pParams->tccParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[0].Yellow));
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-tcc:cyan")))
            {
                pParams->tccParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), reinterpret_cast<double *>(&pParams->tccParam[0].Cyan));
            }
            //-----------------------------------------------------------------------------------
            //                   Region of Interest Testing
            //-----------------------------------------------------------------------------------
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-roi_check")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                pParams->roiCheckParam.mode = Str2ROIMode( strInput[i] );

                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hd"), reinterpret_cast<short int*>(&pParams->roiCheckParam.srcSeed));

                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hd"), reinterpret_cast<short int*>(&pParams->roiCheckParam.dstSeed));
            }
            //-----------------------------------------------------------------------------------
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-i")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_strncopy_s(pParams->strSrcFile, MSDK_MAX_FILENAME_LEN, strInput[i], MSDK_MAX_FILENAME_LEN - 1);
                pParams->strSrcFile[MSDK_MAX_FILENAME_LEN - 1] = 0;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-o")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;

                pParams->strDstFiles.push_back(strInput[i]);
                pParams->isOutput = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pf")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_strncopy_s(pParams->strPerfFile, MSDK_MAX_FILENAME_LEN, strInput[i], MSDK_MAX_FILENAME_LEN - 1);
                pParams->strPerfFile[MSDK_MAX_FILENAME_LEN - 1] = 0;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-scc")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                pParams->fccSource = pParams->frameInfoIn[0].FourCC
                    = Str2FourCC(strInput[i]);

                //if (MFX_FOURCC_I420 == pParams->frameInfoIn[0].FourCC)
                //{
                //    pParams->frameInfoIn[0].FourCC = MFX_FOURCC_YV12; // I420 input is implemented using YV12 internally
                //}

                if(!pParams->frameInfoIn[0].FourCC)
                {
                    vppPrintHelp(strInput[0], MSDK_STRING("Invalid -scc format\n"));
                    return MFX_ERR_UNSUPPORTED;
                }
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-dcc")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                pParams->frameInfoOut[0].FourCC = Str2FourCC( strInput[i] );
                pParams->forcedOutputFourcc = 0;
                if(MFX_FOURCC_I420 == pParams->frameInfoOut[0].FourCC || MFX_FOURCC_YV12 == pParams->frameInfoOut[0].FourCC)
                {
                    pParams->forcedOutputFourcc = pParams->frameInfoOut[0].FourCC;
                    pParams->frameInfoOut[0].FourCC = MFX_FOURCC_NV12; // I420 output is implemented using NV12 internally
                }

                if(!pParams->frameInfoOut[0].FourCC)
                {
                    vppPrintHelp(strInput[0], MSDK_STRING("Invalid -dcc format\n"));
                    return MFX_ERR_UNSUPPORTED;
                }
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-dbitshift")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoOut[0].Shift);
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-dbitdepthluma")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoOut[0].BitDepthLuma);
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-dbitdepthchroma")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoOut[0].BitDepthChroma);
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-sbitshift")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoIn[0].Shift);
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-sbitdepthluma")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoIn[0].BitDepthLuma);
            }
            else if(0 == msdk_strcmp(strInput[i], MSDK_STRING("-sbitdepthchroma")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->frameInfoIn[0].BitDepthChroma);
            }
            else if( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-iopattern")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                pParams->IOPattern = Str2IOpattern( strInput[i] );
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-lib")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                if (0 == msdk_strcmp(strInput[i], MSDK_STRING("sw")) )
                    pParams->ImpLib = MFX_IMPL_SOFTWARE;
                else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("hw")) )
                {
                    pParams->ImpLib = MFX_IMPL_HARDWARE;
                }
            }
#if (defined(LINUX32) || defined(LINUX64))
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-device")))
            {
                if (!pParams->strDevicePath.empty()){
                    msdk_printf(MSDK_STRING("error: you can specify only one device\n"));
                    return MFX_ERR_UNSUPPORTED;
                }
                VAL_CHECK(i+1 == nArgNum);
                pParams->strDevicePath = strInput[++i];
            }
#endif
#if (defined(_WIN64) || defined(_WIN32)) && (MFX_VERSION >= 1031)
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-dGfx")))
            {
                pParams->bPrefferdGfx = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-iGfx")))
            {
                pParams->bPrefferiGfx = true;
            }
#endif
#if defined(D3D_SURFACES_SUPPORT)
            else if( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-d3d")) )
            {
                pParams->IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY|MFX_IOPATTERN_OUT_VIDEO_MEMORY;
                pParams->ImpLib |= MFX_IMPL_VIA_D3D9;
            }
#endif
#if MFX_D3D11_SUPPORT
            else if( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-d3d11")) )
            {
                pParams->IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY|MFX_IOPATTERN_OUT_VIDEO_MEMORY;
                pParams->ImpLib |= MFX_IMPL_VIA_D3D11;
            }
#endif
#ifdef LIBVA_SUPPORT
            else if( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-vaapi")) || 0 == msdk_strcmp(strInput[i], MSDK_STRING("-d3d")) )
            {
                pParams->IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY|MFX_IOPATTERN_OUT_VIDEO_MEMORY;
                pParams->ImpLib |= MFX_IMPL_VIA_VAAPI;
            }
#endif
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-async")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->asyncNum);

            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-perf_opt")) )
            {
                if (pParams->numFrames)
                    return MFX_ERR_UNKNOWN;

                VAL_CHECK(1 + i == nArgNum);
                pParams->bPerf = true;
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hd"), reinterpret_cast<short int*>(&pParams->numFrames));
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hu"), &pParams->numRepeat);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pts_check")) )
            {
                pParams->ptsCheck = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pts_jump")) )
            {
                pParams->ptsJump = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pts_fr")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%lf"), &pParams->ptsFR);
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-pts_advanced")) )
            {
                pParams->ptsAdvanced = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-n")) )
            {
                if (pParams->bPerf)
                    return MFX_ERR_UNKNOWN;

                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_sscanf(strInput[i], MSDK_STRING("%hd"), reinterpret_cast<short int*>(&pParams->numFrames));

            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-p")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_strncopy_s(pParams->strPlgGuid, MSDK_MAX_FILENAME_LEN, strInput[i],MSDK_MAX_FILENAME_LEN-1);
                pParams->strPlgGuid[MSDK_MAX_FILENAME_LEN - 1] = 0;
                pParams->need_plugin = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-plugin_guid")))
            {
                VAL_CHECK(1 + i == nArgNum);
                i++;
                msdk_strncopy_s(pParams->strPlgGuid, MSDK_MAX_FILENAME_LEN, strInput[i],MSDK_MAX_FILENAME_LEN-1);
                pParams->strPlgGuid[MSDK_MAX_FILENAME_LEN - 1] = 0;
                pParams->need_plugin = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-extapi")) )
            {
                pParams->use_extapi = true;
            }
            else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-reset_start")) )
            {
                VAL_CHECK(1 + i == nArgNum);
                msdk_sscanf(strInput[i+1], MSDK_STRING("%hd"), reinterpret_cast<short int*>(&readData));
                i += 2;

                pParams->resetFrmNums.push_back((mfxU16)readData);

                if (MFX_ERR_NONE != vppParseResetPar(strInput, nArgNum, i, pParams, (mfxU32)pParams->resetFrmNums.size(), pDefaultFiltersParam))
                    return MFX_ERR_UNKNOWN;
            }
            else if ( 0 == msdk_strcmp(strInput[i], MSDK_STRING("-cf_disable")) )
            {
                pParams->colorfillParam[0].mode = VPP_FILTER_ENABLED_CONFIGURED;
                pParams->colorfillParam[0].Enable = MFX_CODINGOPTION_OFF;
            }
            else
            {
                msdk_printf(MSDK_STRING("Unknown option: %s\n"), strInput[i]);

                return MFX_ERR_UNKNOWN;
            }
        }
    }

    if ((pParams->ImpLib & MFX_IMPL_HARDWARE) && !(pParams->ImpLib & MFX_IMPL_VIA_D3D11 || pParams->ImpLib & MFX_IMPL_VIA_D3D9))
    {
        pParams->ImpLib = MFX_IMPL_HARDWARE |
        #ifdef LIBVA_SUPPORT
                MFX_IMPL_VIA_VAAPI;
        #else
                MFX_IMPL_VIA_D3D11;
        #endif
    }

    std::vector<sOwnFrameInfo>::iterator it = pParams->frameInfoIn.begin();
    while(it != pParams->frameInfoIn.end())
    {
        if (NOT_INIT_VALUE == it->CropW)
        {
            it->CropW = it->nWidth;
        }

        if (NOT_INIT_VALUE == it->CropH)
        {
            it->CropH = it->nHeight;
        }
        it++;
    }

    it = pParams->frameInfoOut.begin();
    while(it != pParams->frameInfoOut.end())
    {
        if (NOT_INIT_VALUE == it->CropW)
        {
            it->CropW = it->nWidth;
        }

        if (NOT_INIT_VALUE == it->CropH)
        {
            it->CropH = it->nHeight;
        }
        it++;
    }

    if (0 == msdk_strlen(pParams->strSrcFile) && pParams->compositionParam.mode != VPP_FILTER_ENABLED_CONFIGURED)
    {
        vppPrintHelp(strInput[0], MSDK_STRING("Source file name not found"));
        return MFX_ERR_UNSUPPORTED;
    };

    if (1 != pParams->strDstFiles.size() && (pParams->resetFrmNums.size() + 1) != pParams->strDstFiles.size())
    {
        vppPrintHelp(strInput[0], MSDK_STRING("Destination file name should be declared once or for each parameter set (reset case)"));
        return MFX_ERR_UNSUPPORTED;
    };

    if (0 == pParams->IOPattern)
    {
        vppPrintHelp(strInput[0], MSDK_STRING("Incorrect IOPattern"));
        return MFX_ERR_UNSUPPORTED;
    }

    if ((pParams->ImpLib & MFX_IMPL_SOFTWARE) && (pParams->IOPattern & (MFX_IOPATTERN_IN_VIDEO_MEMORY|MFX_IOPATTERN_OUT_VIDEO_MEMORY)))
    {
        msdk_printf(MSDK_STRING("Warning: IOPattern has been reset to 'sys_to_sys' mode because software library implementation is selected."));
        pParams->IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY|MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
    }

#if (defined(_WIN64) || defined(_WIN32)) && (MFX_VERSION >= 1031)
    if (pParams->bPrefferdGfx && pParams->bPrefferiGfx)
    {
        msdk_printf(MSDK_STRING("Warning: both dGfx and iGfx flags set. iGfx will be preffered"));
        pParams->bPrefferdGfx = false;
    }
#endif

    // Align values of luma and chroma bit depth if only one of them set by user
    AdjustBitDepth(*pParams);

    return MFX_ERR_NONE;

} // mfxStatus vppParseInputString( ... )

bool CheckInputParams(msdk_char* strInput[], sInputParams* pParams )
{
    // Setting  default width and height if it was omitted. For composition case parameters should be define explicitly
    if (pParams->frameInfoOut[0].nWidth == 0)
    {
        if (pParams->compositionParam.mode == VPP_FILTER_ENABLED_CONFIGURED)
        {
            vppPrintHelp(strInput[0], MSDK_STRING("ERROR: Destination width should be set explicitely in case of composition mode.\n"));
            return false;
        }
        pParams->frameInfoOut[0].nWidth = pParams->frameInfoIn[0].nWidth;
        pParams->frameInfoOut[0].CropW = pParams->frameInfoIn[0].CropW;
        pParams->frameInfoOut[0].CropX = 0;
    }

    if (pParams->frameInfoOut[0].nHeight == 0)
    {
        if (pParams->compositionParam.mode == VPP_FILTER_ENABLED_CONFIGURED)
        {
            vppPrintHelp(strInput[0], MSDK_STRING("ERROR: Destination height should be set explicitely in case of composition mode.\n"));
            return false;
        }
        pParams->frameInfoOut[0].nHeight = pParams->frameInfoIn[0].nHeight;
        pParams->frameInfoOut[0].CropH = pParams->frameInfoIn[0].CropH;
        pParams->frameInfoOut[0].CropY = 0;
    }

    // Checking other parameters
    if (0 == pParams->asyncNum)
    {
        vppPrintHelp(strInput[0], MSDK_STRING("Incompatible parameters: [ayncronous number must exceed 0]\n"));
        return false;
    }

    for (mfxU32 i = 0; i < pParams->rotate.size(); i++)
    {
        if (pParams->rotate[i] != 0 && pParams->rotate[i] != 90 && pParams->rotate[i] != 180 && pParams->rotate[i] != 270)
        {
            vppPrintHelp(strInput[0], MSDK_STRING("Invalid -rotate parameter: supported values 0, 90, 180, 270\n"));
            return false;
        }
    }

    for (mfxU32 i = 0; i < pParams->numStreams; i++)
    {
        const mfxVPPCompInputStream& is = pParams->compositionParam.streamInfo[i].compStream;

        if ((pParams->frameInfoOut[0].nWidth < is.DstW + is.DstX) ||
            (pParams->frameInfoOut[0].nHeight < is.DstH + is.DstY))
        {
            vppPrintHelp(strInput[0], MSDK_STRING("One of composing frames cannot fit into destination frame.\n"));
            return false;
        }
    }

    return true;

} // bool CheckInputParams(msdk_char* strInput[], sInputVppParams* pParams )

// trim from start
static inline std::string &ltrim(std::string &s) {
    s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char c){ return !std::isspace(c); }));
    return s;
}

// trim from end
static inline std::string &rtrim(std::string &s) {
    s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char c){ return !std::isspace(c); }).base(), s.end());
    return s;
}

// trim from both ends
static inline std::string &trim(std::string &s) {
    return ltrim(rtrim(s));
}

void getPair(std::string line, std::string &key, std::string &value)
{
    std::istringstream iss(line);
    getline(iss, key,   '=');
    getline(iss, value, '=');
    trim(key);
    trim(value);
}

mfxStatus ParseCompositionParfile(const msdk_char* parFileName, sInputParams* pParams)
{
    mfxStatus sts = MFX_ERR_NONE;
    if(msdk_strlen(parFileName) == 0)
        return MFX_ERR_UNKNOWN;

    MSDK_ZERO_MEMORY(pParams->inFrameInfo);

    std::string line;
    std::string key, value;
    mfxU8 nStreamInd = 0;
    mfxU8 firstStreamFound = 0;
    std::ifstream stream(parFileName);
    if (stream.fail())
        return MFX_ERR_UNKNOWN;

    while (getline(stream, line) && nStreamInd < MAX_INPUT_STREAMS)
    {
        getPair(line, key, value);
        if (key.compare("width") == 0)
        {
            pParams->inFrameInfo[nStreamInd].nWidth = (mfxU16) MSDK_ALIGN16(atoi(value.c_str()));
        }
        else if (key.compare("height") == 0)
        {
            pParams->inFrameInfo[nStreamInd].nHeight = (MFX_PICSTRUCT_PROGRESSIVE == pParams->inFrameInfo[nStreamInd].PicStruct)?
                (mfxU16) MSDK_ALIGN16(atoi(value.c_str())) : (mfxU16) MSDK_ALIGN32(atoi(value.c_str()));
        }
        else if (key.compare("cropx") == 0)
        {
            pParams->inFrameInfo[nStreamInd].CropX = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("cropy") == 0)
        {
            pParams->inFrameInfo[nStreamInd].CropY = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("cropw") == 0)
        {
            pParams->inFrameInfo[nStreamInd].CropW = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("croph") == 0)
        {
            pParams->inFrameInfo[nStreamInd].CropH = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("framerate") == 0)
        {
            pParams->inFrameInfo[nStreamInd].dFrameRate = (mfxF64) atof(value.c_str());
        }
        else if (key.compare("fourcc") == 0)
        {
            const mfxU16 len_size = 5;
            msdk_char fourcc[len_size];
            for (mfxU16 i = 0; i < (value.size() > len_size ? len_size : value.size()); i++)
                fourcc[i] = value.at(i);
            fourcc[len_size-1]=0;
            pParams->inFrameInfo[nStreamInd].FourCC = Str2FourCC(fourcc);

            if(!pParams->inFrameInfo[nStreamInd].FourCC)
            {
                msdk_printf(MSDK_STRING("Invalid fourcc parameter in par file: %s\n"),fourcc);
                return MFX_ERR_INVALID_VIDEO_PARAM;
            }
        }
        else if (key.compare("picstruct") == 0)
        {
            pParams->inFrameInfo[nStreamInd].PicStruct = GetPicStruct((mfxI8)atoi(value.c_str()));
        }
        else if (key.compare("dstx") == 0)
        {
            pParams->compositionParam.streamInfo[nStreamInd].compStream.DstX = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("dsty") == 0)
        {
            pParams->compositionParam.streamInfo[nStreamInd].compStream.DstY = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("dstw") == 0)
        {
            pParams->compositionParam.streamInfo[nStreamInd].compStream.DstW = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("dsth") == 0)
        {
            pParams->compositionParam.streamInfo[nStreamInd].compStream.DstH = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("GlobalAlphaEnable") == 0)
        {
            pParams->compositionParam.streamInfo[nStreamInd].compStream.GlobalAlphaEnable = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("GlobalAlpha") == 0)
        {
            pParams->compositionParam.streamInfo[nStreamInd].compStream.GlobalAlpha = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("PixelAlphaEnable") == 0)
        {
            pParams->compositionParam.streamInfo[nStreamInd].compStream.PixelAlphaEnable = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("LumaKeyEnable") == 0)
        {
            pParams->compositionParam.streamInfo[nStreamInd].compStream.LumaKeyEnable = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("LumaKeyMin") == 0)
        {
            pParams->compositionParam.streamInfo[nStreamInd].compStream.LumaKeyMin = (mfxU16) atoi(value.c_str());
        }
        else if (key.compare("LumaKeyMax") == 0)
        {
            pParams->compositionParam.streamInfo[nStreamInd].compStream.LumaKeyMax = (mfxU16) atoi(value.c_str());
        }
        else if ((key.compare("stream") == 0 || key.compare("primarystream") == 0) && nStreamInd < (MAX_INPUT_STREAMS - 1))
        {
            const mfxU16 len_size = MSDK_MAX_FILENAME_LEN - 1;

            if (firstStreamFound == 1)
            {
                nStreamInd ++;
            }
            else
            {
                nStreamInd = 0;
                firstStreamFound = 1;
            }
            pParams->inFrameInfo[nStreamInd].CropX = 0;
            pParams->inFrameInfo[nStreamInd].CropY = 0;
            pParams->inFrameInfo[nStreamInd].CropW = NOT_INIT_VALUE;
            pParams->inFrameInfo[nStreamInd].CropH = NOT_INIT_VALUE;
            mfxU16 i = 0;
            for (; i < (value.size() > len_size ? len_size : value.size()); i++)
                pParams->compositionParam.streamInfo[nStreamInd].streamName[i] = value.at(i);
            pParams->compositionParam.streamInfo[nStreamInd].streamName[i]=0;
            pParams->inFrameInfo[nStreamInd].dFrameRate = 30;
            pParams->inFrameInfo[nStreamInd].PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
        }
    }

    pParams->numStreams = nStreamInd + 1;

    for(int i=0;i<pParams->numStreams;i++)
    {
        if(!pParams->inFrameInfo[i].FourCC)
        {
            msdk_printf(MSDK_STRING("Fourcc parameter of stream %d in par file is invalid or missing.\n"),i);
            return MFX_ERR_INVALID_VIDEO_PARAM;
        }
    }
    return sts;
}

/* EOF */
