/*********************************************************************************
*                                                                               *
* Copyright (c) 2008 Samsung System LSI											*
* All rights reserved.                                                          *
*                                                                               *
* This software is test sample code for Hybrid Divx Decoder						*
*																				*
* Author : Jiyoung Shin 								    						
* Last Changed : 2008.08.05 													
*********************************************************************************/
#include <windows.h>
#include "SsbSipMfcApi.h"
#include "SsbSipMfcConfig.h"

#define MAX_FILENAME_SIZE			256
#define MAX_MSG_SIZE 				512
#define MAX_CFG_FILE_SIZE			20480
#define MAX_PARAM_NUM 				3
#define PROFILE_IDC     			77
#define LEVEL_IDC       			31
#define INIT_FRAME_RATE 			30
#define MIN_QP          			0
#define MAX_QP          			51
#define SHIFT_QP        			12

typedef enum 
{
  UVLC,  CABAC
} SymbolMode;

typedef struct
{
	char infile[MAX_FILENAME_SIZE];     
	int no_frames;                
	int ProfileIDC;               //!< profile idc
  	int LevelIDC;                 //!< level idc
	int img_width;                //!< image width  (must be a multiple of 16 pels)
 	int img_height;               //!< image height (must be a multiple of 16 pels)
	int intra_period;             //!< Random Access period though intra
	int IDR_period;
	int num_ref_frames;           //!< number of reference frames to be used
	int NUM_REFS_FOR_P;
	int SliceMode;
	int SliceArgument;
	int successive_Bframe;        //!< number of B frames that will be used
	int jumpd;                    //!< number of frames to skip in input sequence (e.g 2 takes frame 0,3,6,9...)
	int directInferenceFlag;      //!< Direct Inference Flag
	int LFDisableIdc;
 	int LFAlphaC0Offset;
 	int LFBetaOffset;
	int symbol_mode;              //!< Specifies the mode the symbols are mapped on bits
	int PicInterlace;           //!< picture adaptive frame/field
	int Transform8x8Mode;
	int IntraMD8x8Disable;
	int IntraMD4x4Disable;
	int IntraMD4x4Weight;
	int IntraMD8x8Weight;
	int IntraMD16x16Weight;
 	int InterSearch16x8;
  	int InterSearch8x16;
  	int InterSearch8x8;
  	int DisableHpelME;
	int DisableQpelME;
 	int MDInterWeightPPS;
	int MDIntraWeightPPS;
	int RandomIntraMBRefresh;     //!< Number of pseudo-random intra-MBs per picture
	int pad_ctrl_on;
	int luma_pad_val;
	int cb_pad_val;
	int cr_pad_val;

    /// A company
	int REF_PIC_SEL;
 	int REF_PIC_IDX;
	int intra_slice_flag;
	int skip_slice_flag;
	int frame_type_ctl_ena;
	int frame_type;
	int slice_mb_count[32];           //!< Argument to the specified slice algorithm
	int max_bit_count_enable;		// HRD : enable maximum bit limitation
  	int max_bit_count;				// HRD : maixmum bit threshold
  	int min_bit_count_enable;		// HRD : enable minimum bit limitation
 	 int min_bit_count;				// HRD : minimum bit threshold

    ///RC
	int enablefrmratecontrol;
	int enablembratecontrol;
	int FrameRate;
	int BitRate;
	unsigned int frame_qp;
	unsigned int qs_code_max;
  	unsigned int qs_code_min;
	unsigned int rf;
	unsigned int dark_disable;
	unsigned int smooth_disable;
	unsigned int static_disable;
	unsigned int act_disable;	
	int acd_intra_motion_en;	// enable motion estimation phase of intra picture
  
}H264InputParam;

typedef struct {
  char *TokenName;
  void *Place;
  int Type;
  int Default;
  int param_limits; //! 0: no limits, 1: both min and max, 2: only min (i.e. no negatives), 3: specialcase for QPs since min needs bitdepth_qp_scale
  int min_limit;
  int max_limit;
  int use_field;
} MapList;

static H264InputParam oH264ConfigInput;
static MapList MapH264Enc[] = {
	
    {"InputFile", &oH264ConfigInput.infile, 1, 0, 0, 0, 0, 1},
	{"FramesToBeEncoded", &oH264ConfigInput.no_frames, 0, 30, 2, 1, 0, 1},

	//// / NORMAL ////////
	{"ProfileIDC", &oH264ConfigInput.ProfileIDC, 0, PROFILE_IDC, 0, 0, 0, 1},
	{"LevelIDC", &oH264ConfigInput.LevelIDC, 0, LEVEL_IDC, 0, 0, 0, 1},
	{"SourceWidth", &oH264ConfigInput.img_width, 0, 176, 1, 32, 1280, 1},
	{"SourceHeight", &oH264ConfigInput.img_height, 0, 144, 1, 32, 720, 1},
	{"IntraPeriod", &oH264ConfigInput.intra_period, 0, 24, 1, 0, 65536, 1},  //not used in MFCV5.0
	{"IDRPeriod", &oH264ConfigInput.IDR_period, 0, 24, 1, 0, 65536, 1},
	{"NumberReferenceFrames", &oH264ConfigInput.num_ref_frames, 0, 1, 1, 1, 16, 1},
	{"NUM_REFS_FOR_P", &oH264ConfigInput.NUM_REFS_FOR_P, 0, 1, 1, 0, 100, 1},   // min,max??????
	{"SliceMode", &oH264ConfigInput.SliceMode, 0, 0, 1, 0, 4, 1},
	{"SliceArgument", &oH264ConfigInput.SliceArgument, 0, 0, 1, 0, 9999999, 1}, 
	{"NumberBFrames", &oH264ConfigInput.successive_Bframe, 0, 0, 1, 1, 2, 0},
	{"FrameSkip", &oH264ConfigInput.jumpd, 0, 0, 1, 1, 2, 0}, 
	{"DirectInferenceFlag", &oH264ConfigInput.directInferenceFlag, 0, 1, 1, 0, 1, 0},
	{"LoopFilterDisable", &oH264ConfigInput.LFDisableIdc, 0, 0, 1, 0, 2, 1},
	{"LoopFilterAlphaC0Offset", &oH264ConfigInput.LFAlphaC0Offset, 0, 0, 1, -6, 6, 1},
	{"LoopFilterBetaOffset", &oH264ConfigInput.LFBetaOffset, 0, 0, 1, -6, 6, 1},
	{"SymbolMode", &oH264ConfigInput.symbol_mode, 0, 0, 1, UVLC, CABAC, 1},
	{"PicInterlace", &oH264ConfigInput.PicInterlace, 0, 0, 1, 0, 1, 0},
	{"Transform8x8Mode", &oH264ConfigInput.Transform8x8Mode, 0, 0, 1, 0, 1, 0},
	{"IntraMD8x8Disable", &oH264ConfigInput.IntraMD8x8Disable, 0, 0, 1, 0, 1, 1},
	{"IntraMD4x4Disable", &oH264ConfigInput.IntraMD4x4Disable, 0, 0, 1, 0, 1, 1},
	{"IntraMD4x4Weight", &oH264ConfigInput.IntraMD4x4Weight, 0, 0, 1, 0, 32767, 1},
	{"IntraMD8x8Weight", &oH264ConfigInput.IntraMD8x8Weight, 0, 0, 1, 0, 32767, 1},
	{"IntraMD16x16Weight", &oH264ConfigInput.IntraMD16x16Weight, 0, 0, 1, 0, 32767, 1},
	{"InterSearch16x8", &oH264ConfigInput.InterSearch16x8, 0, 1, 1, 0, 1, 1},
	{"InterSearch8x16", &oH264ConfigInput.InterSearch8x16, 0, 1, 1, 0, 1, 1},
	{"InterSearch8x8", &oH264ConfigInput.InterSearch8x8, 0, 1, 1, 0, 1, 1},
	{"DisableHpelME", &oH264ConfigInput.DisableHpelME, 0, 0, 1, 0, 1, 1},
	{"DisableQpelME", &oH264ConfigInput.DisableQpelME, 0, 0, 1, 0, 1, 1},
	{"MDInterWeightPPS", &oH264ConfigInput.MDInterWeightPPS, 0, 170, 1, 0, 32767, 1},	// min/max is not confirmed
	{"MDIntraWeightPPS", &oH264ConfigInput.MDIntraWeightPPS, 0, 300, 1, 0, 32767, 1},	// min/max is not confirmed
	{"RandomIntraMBRefresh", &oH264ConfigInput.RandomIntraMBRefresh, 0, 0, 2, 0, 0, 0}, //CIR
	{"PAD_CTRL_ON", &oH264ConfigInput.pad_ctrl_on, 0, 0, 1, 0, 1, 1},
	{"LUMA_PAD_VAL", &oH264ConfigInput.luma_pad_val, 0, 0, 1, 0, 255, 1},
	{"CB_PAD_VAL", &oH264ConfigInput.cb_pad_val, 0, 0, 1, 0, 255, 1},
	{"CR_PAD_VAL", &oH264ConfigInput.cr_pad_val, 0, 0, 1, 0, 255, 1},


	 //// A compay ////// 
	{"REF_PIC_SEL", &oH264ConfigInput.REF_PIC_SEL, 0, 0, 1, 0, 1, 1},
	{"REF_PIC_IDX", &oH264ConfigInput.REF_PIC_IDX, 0, 0, 1, 0, 14, 1},
	{"INTRA_SLICE_FLAG", &oH264ConfigInput.intra_slice_flag, 0, 0, 1, 0, 1, 1}, //max is not confirmed
	{"SKIP_SLICE_FLAG", &oH264ConfigInput.skip_slice_flag, 0, 0, 1, 0, 1, 1},  //max is not confirmed
	{"FRAME_TYPE_CTL_ENA", &oH264ConfigInput.frame_type_ctl_ena, 0, 0, 1, 0, 1, 1},
	{"FrameType", &oH264ConfigInput.frame_type, 0, 0, 1, 0, 2, 1},
	{"VAR_MB_CNT0", &oH264ConfigInput.slice_mb_count[0], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT1", &oH264ConfigInput.slice_mb_count[1], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT2", &oH264ConfigInput.slice_mb_count[2], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT3", &oH264ConfigInput.slice_mb_count[3], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT4", &oH264ConfigInput.slice_mb_count[4], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT5", &oH264ConfigInput.slice_mb_count[5], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT6", &oH264ConfigInput.slice_mb_count[6], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT7", &oH264ConfigInput.slice_mb_count[7], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT8", &oH264ConfigInput.slice_mb_count[8], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT9", &oH264ConfigInput.slice_mb_count[9], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT10", &oH264ConfigInput.slice_mb_count[10], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT11", &oH264ConfigInput.slice_mb_count[11], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT12", &oH264ConfigInput.slice_mb_count[12], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT13", &oH264ConfigInput.slice_mb_count[13], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT14", &oH264ConfigInput.slice_mb_count[14], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT15", &oH264ConfigInput.slice_mb_count[15], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT16", &oH264ConfigInput.slice_mb_count[16], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT17", &oH264ConfigInput.slice_mb_count[17], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT18", &oH264ConfigInput.slice_mb_count[18], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT19", &oH264ConfigInput.slice_mb_count[19], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT20", &oH264ConfigInput.slice_mb_count[20], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT21", &oH264ConfigInput.slice_mb_count[21], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT22", &oH264ConfigInput.slice_mb_count[22], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT23", &oH264ConfigInput.slice_mb_count[23], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT24", &oH264ConfigInput.slice_mb_count[24], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT25", &oH264ConfigInput.slice_mb_count[25], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT26", &oH264ConfigInput.slice_mb_count[26], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT27", &oH264ConfigInput.slice_mb_count[27], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT28", &oH264ConfigInput.slice_mb_count[28], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT29", &oH264ConfigInput.slice_mb_count[29], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT30", &oH264ConfigInput.slice_mb_count[30], 0, 0, 0, 0, 0, 1},
	{"VAR_MB_CNT31", &oH264ConfigInput.slice_mb_count[31], 0, 0, 0, 0, 0, 1},
	{"HRDMaxBitCountEnable", &oH264ConfigInput.max_bit_count_enable, 0, 0, 1, 0, 1, 1},
	{"HRDMaxBitCount", &oH264ConfigInput.max_bit_count, 0, 0, 1, 0, 0x7FFFFFFF, 1},
	{"HRDMinBitCountEnable", &oH264ConfigInput.min_bit_count_enable, 0, 0, 1, 0, 1, 1},
	{"HRDMinBitCount", &oH264ConfigInput.min_bit_count, 0, 0, 1, 0, 0x7FFFFFFF, 1},
	/////// RC ////////
	{"EnableFRMRateControl", &oH264ConfigInput.enablefrmratecontrol, 0, 0, 1, 0, 1, 1},
	{"EnableMBRateControl", &oH264ConfigInput.enablembratecontrol, 0, 0, 1, 0, 1, 1},
	{"FrameRate", &oH264ConfigInput.FrameRate, 0, INIT_FRAME_RATE, 1, 1, 255, 1},
	{"Bitrate", &oH264ConfigInput.BitRate, 0, 10000, 2, 1000, 0, 1},   ///min/max ?????
	{"FrameQp", &oH264ConfigInput.frame_qp, 0, 24, 1, 0, 51, 1},
	{"QSCodeMax", &oH264ConfigInput.qs_code_max, 0, 45, 1, 0, 51, 1},
	{"QSCodeMin", &oH264ConfigInput.qs_code_min, 0, 25, 1, 0, 51, 1},
	{"CBRPeriodRf", &oH264ConfigInput.rf, 0, 2, 1, 0, 65535, 1},	// min/max is not confirmed
	{"DarkDisable", &oH264ConfigInput.dark_disable, 0, 0, 1, 0, 1, 1},   
	{"SmoothDisable", &oH264ConfigInput.smooth_disable, 0, 0, 1, 0, 1, 1},
	{"StaticDisable", &oH264ConfigInput.static_disable, 0, 0, 1, 0, 1, 1},
	{"ActivityDisable", &oH264ConfigInput.act_disable, 0, 0, 1, 0, 1, 1},
	{"ACDIntraMotionEn", &oH264ConfigInput.acd_intra_motion_en, 0, 0, 1, 0, 1, 1},


	{NULL, NULL, -1, 0, 0, 0, 0, 0}
};

MapList *FindItem(char *item_name)
{
	int idx=0;
	
	while(MapH264Enc[idx].TokenName != NULL)
	{			
		if(strncmp(MapH264Enc[idx].TokenName, item_name, strlen(MapH264Enc[idx].TokenName))==0)
		{
			return &MapH264Enc[idx];
		}
		idx++;
	}

	// nothing matched with current Map list
	return NULL;
}

int Split(char **str_arr, char *msg, const char *spliter, const char comment)
{
	int len;
	int len_ns;	// length with no space
	int i;
	int ret=1;
	char *comment_pos;	
	char *str_rs;	// remove space
	char *p;
	int num_item;


	comment_pos = strchr(msg, comment);
	if(comment_pos==NULL)
	{
		len = strlen(msg);
	}
	else
	{
		len = (int)(comment_pos-msg);
	}

	// check invalid parameter size
	if(len<5)
	{
		return 0;
	}
		
	str_rs = (char *)malloc(len);
	strcpy(str_rs, "");

	len_ns = 0;
	for(i=0 ; i<len ; i++)
	{
		// remove unused characters
		if(msg[i]!='\n' && msg[i]!='\r' && msg[i]!='\t')
		{
			strncat(str_rs, &msg[i], 1);
			len_ns++;
		}
	}
	
	num_item = 0;

	// separate token and value
	if((p = strtok(str_rs, spliter))!=NULL)
	{
		strcpy(str_arr[num_item++], p);
	}

	// check small length parameter (invalid)
	if(len_ns<5 || p==NULL)
		ret = 0;

	while(p!=NULL)
	{
		if((p = strtok(NULL, spliter))!=NULL)
		{
			strcpy(str_arr[num_item++], p);
		}
	}

	if(num_item != 2)
		ret = 0;
		
	free(str_rs);
	
	return ret;

}

int Map2H264EncConfig(char **line_item)
{
	MapList *cur_map;

	// line_item[0] is TokenName
	cur_map = FindItem(line_item[0]);
	if(cur_map!=NULL)
	{
		if(cur_map->Type == 0)
		{
			// line_item[1] is Default value, type is integer
			int *cur_value = (int *)cur_map->Place;
			*cur_value = atoi(line_item[1]);
		}
		else if(cur_map->Type == 1)
		{
			// line_item[1] is Default value, type is string
			char *cur_string = (char *)cur_map->Place;
			strcpy(cur_string, line_item[1]);
		}
		return 1;
	}
	else
	{
		// nothing to parse or wrong param
		return 0;
	}
}

void SetH264Config(SSBSIP_MFC_ENC_H264_PARAM *param,  char *inputFile, int *NumOfFrame)
{
	strcpy(inputFile, oH264ConfigInput.infile);

	*NumOfFrame		= oH264ConfigInput.no_frames;
	param->SourceWidth			= oH264ConfigInput.img_width;
	param->SourceHeight			= oH264ConfigInput.img_height;
	
	param->ProfileIDC				= oH264ConfigInput.ProfileIDC;
	param->LevelIDC				= oH264ConfigInput.LevelIDC;
	param->IDRPeriod				= oH264ConfigInput.IDR_period;
	param->NumberReferenceFrames	= oH264ConfigInput.num_ref_frames;
	param->NumberRefForPframes	= oH264ConfigInput.NUM_REFS_FOR_P;
	param->SliceMode				= oH264ConfigInput.SliceMode;
	param->SliceArgument			= oH264ConfigInput.SliceArgument;
	
	param->NumberBFrames			= oH264ConfigInput.successive_Bframe;
	
	param->LoopFilterDisable		= oH264ConfigInput.LFDisableIdc;
	param->LoopFilterAlphaC0Offset	= oH264ConfigInput.LFAlphaC0Offset;
	param->LoopFilterBetaOffset	= oH264ConfigInput.LFBetaOffset;
	
	param->SymbolMode				= oH264ConfigInput.symbol_mode;
	
	param->PictureInterlace		= oH264ConfigInput.PicInterlace;
	
	param->Transform8x8Mode		= oH264ConfigInput.Transform8x8Mode;
	
	param->RandomIntraMBRefresh	= oH264ConfigInput.RandomIntraMBRefresh;
	
	param->PadControlOn			= oH264ConfigInput.pad_ctrl_on;
	param->LumaPadVal				= oH264ConfigInput.luma_pad_val;
	param->CbPadVal				= oH264ConfigInput.cb_pad_val;
	param->CrPadVal				= oH264ConfigInput.cr_pad_val;
		
    ///RC
	param->EnableFRMRateControl	= oH264ConfigInput.enablefrmratecontrol;
	param->EnableMBRateControl	= oH264ConfigInput.enablembratecontrol;
	param->FrameRate				= oH264ConfigInput.FrameRate;
	param->Bitrate				= oH264ConfigInput.BitRate;
	param->FrameQp				= oH264ConfigInput.frame_qp;
	param->QSCodeMax				= oH264ConfigInput.qs_code_max;
  	param->QSCodeMin				= oH264ConfigInput.qs_code_min;
	param->CBRPeriodRf			= oH264ConfigInput.rf;
	param->DarkDisable			= oH264ConfigInput.dark_disable;
	param->SmoothDisable			= oH264ConfigInput.smooth_disable;
	param->StaticDisable			= oH264ConfigInput.static_disable;
	param->ActivityDisable		= oH264ConfigInput.act_disable;
}

void MFC_ParseConfigFile(char *uConfigFileBufAddr, SSBSIP_MFC_CODEC_TYPE codec_type, void *encParam,  char *inputFile, int *NumOfFrame, int *width, int *height)
{
	char* pConfigFileStr = uConfigFileBufAddr;
	char *param_line;
			
	printf("Parsing Config File...START\n");
	
	if (codec_type == H264_ENC)
	{
		char *param_arr[MAX_PARAM_NUM];
		char *param_line[512];
		unsigned int uPara_Count;
		unsigned int i, j=0;
		SSBSIP_MFC_ENC_H264_PARAM *h264_param;

		printf("Parsing H264_ENC\n");
		h264_param = (SSBSIP_MFC_ENC_H264_PARAM *)encParam;
		h264_param->codecType = codec_type;
		for(i=0 ; i<MAX_PARAM_NUM ; i++)
			param_arr[i] = (char *)malloc(MAX_MSG_SIZE);

		i = 0;
		param_line[i] = strtok(pConfigFileStr, "\r\n");
		
		while(1)
		{	
			if (j != 0)
				param_line[i] = strtok(NULL, "\r\n");
			if (param_line[i]== NULL)
				break;
			j++;
			if ((param_line[i][0] == ' ')||(param_line[i][0] == '\t')||(param_line[i][0] == '#')||(param_line[i][0] == '\n')||(param_line[i][0] == '\r'))
				continue;
			i++;
			
		}

		uPara_Count = i-1;

		for (i=0;i<uPara_Count;i++)
		{
			if(Split(&param_arr[0], param_line[i], "=", '#'))
			{
				Map2H264EncConfig(param_arr);
			}

			if(0==strcmp(param_arr[0], "CompleteSeqParam") ||0==strcmp(param_arr[0], "CompleteFrameParam"))
			{
				printf("ACK CompleteSeqParam \n");
				break;
			}		
		}

		for(i=0 ; i<MAX_PARAM_NUM ; i++)
			free(param_arr[i]);

		SetH264Config(h264_param, inputFile, NumOfFrame);

		h264_param->ProfileIDC = 
			(h264_param->ProfileIDC == 66) ? 2 :	// baseline, oMfcEncConfig[oMfc.m_uProcessIdx].m_uProfileIDC == 66
			(h264_param->ProfileIDC == 77) ? 0 :	// main
			1 ;	// high

		*width = h264_param->SourceWidth;
		*height = h264_param->SourceHeight;
		h264_param->FrameQp_P = h264_param->FrameQp+1;
		h264_param->FrameQp_B = h264_param->FrameQp+3;

		printf("inputFile : %s\n", inputFile);
		printf("NumOfFrame : %d\n", *NumOfFrame);
		printf("SourceWidth : %d\n", h264_param->SourceWidth);
		printf("SourceHeight : %d\n", h264_param->SourceHeight);
		printf("ProfileIDC : %d\n", h264_param->ProfileIDC);
		printf("LevelIDC : %d\n", h264_param->LevelIDC);
		printf("IDRPeriod : %d\n", h264_param->IDRPeriod);
		printf("NumberReferenceFrames : %d\n", h264_param->NumberReferenceFrames);
		printf("NumberRefForPframes : %d\n", h264_param->NumberRefForPframes);
		printf("SliceMode : %d\n", h264_param->SliceMode);
		printf("SliceArgument : %d\n", h264_param->SliceArgument);
		printf("NumberBFrames : %d\n", h264_param->NumberBFrames);
		printf("LoopFilterDisable : %d\n", h264_param->LoopFilterDisable);
		printf("LoopFilterAlphaC0Offset : %d\n", h264_param->LoopFilterAlphaC0Offset);
		printf("SymbolMode : %d\n", h264_param->SymbolMode);
		printf("PictureInterlace : %d\n", h264_param->PictureInterlace);
		printf("Transform8x8Mode : %d\n", h264_param->Transform8x8Mode);
		printf("RandomIntraMBRefresh : %d\n", h264_param->RandomIntraMBRefresh);
		printf("PadControlOn : %d\n", h264_param->PadControlOn);
		printf("LumaPadVal : %d\n", h264_param->LumaPadVal);
		printf("CbPadVal : %d\n", h264_param->CbPadVal);
		printf("CrPadVal : %d\n", h264_param->CrPadVal);
		printf("EnableFRMRateControl : %d\n", h264_param->EnableFRMRateControl);
		printf("EnableMBRateControl : %d\n", h264_param->EnableMBRateControl);
		printf("FrameRate : %d\n", h264_param->FrameRate);
		printf("Bitrate : %d\n", h264_param->Bitrate);
		printf("FrameQp : %d\n", h264_param->FrameQp);
		printf("QSCodeMax : %d\n", h264_param->QSCodeMax);
		printf("QSCodeMin : %d\n", h264_param->QSCodeMin);
		printf("CBRPeriodRf : %d\n", h264_param->CBRPeriodRf);
		printf("DarkDisable : %d\n", h264_param->DarkDisable);
		printf("SmoothDisable : %d\n", h264_param->SmoothDisable);
		printf("StaticDisable : %d\n", h264_param->StaticDisable);
		printf("ActivityDisable : %d\n", h264_param->ActivityDisable);
	}	
	else if(codec_type == MPEG4_ENC)
	{
		char* ptemp;
		char* ptemp2;
		unsigned int j=0;
		SSBSIP_MFC_ENC_MPEG4_PARAM *mpeg4_param;
		int	profileLevel, ResyncEnable, ResyncType;
		int	SliceArgument1, SliceArgument2;

		printf("Parsing MPEG4_ENC\n");
		mpeg4_param = (SSBSIP_MFC_ENC_MPEG4_PARAM *)encParam;
		mpeg4_param->codecType = codec_type;
		param_line = strtok(pConfigFileStr, "\r\n");

		do
		{	
			if ((param_line[0] == '\n')||(param_line[0] == '\r'))
				continue;

			ptemp  = strchr(param_line, '\t');
			if(ptemp != NULL)
				*ptemp = NULL;

			j++;

			if(j != 16){
				ptemp2 = strchr(param_line, ' ');
				if(ptemp2 != NULL)
					*ptemp2 = NULL;
			}


			switch (j)
			{
				case 16:	strcpy(inputFile, param_line);			break;
				case 5:		{
								profileLevel = atoi(param_line);
								if(profileLevel == 0)
    							{
      								mpeg4_param->ProfileIDC	= 0;
    								mpeg4_param->LevelIDC	= 3;
    							}
    							else
    							{
    								if(profileLevel == 8)
									{
										// SP@L0
										mpeg4_param->ProfileIDC	= 0;
										mpeg4_param->LevelIDC	= 0;
									}
									else if((profileLevel&0xf0) == 0)
    								{
    									// simple profile
    									mpeg4_param->ProfileIDC= 0;
    									mpeg4_param->LevelIDC	= profileLevel & 0xf;
    								}
    								else
    								{
    									// Advanced simple profile
    									mpeg4_param->ProfileIDC	= 1;
    									mpeg4_param->LevelIDC	= profileLevel & 0xf;
    								}
    							}
								break;
							}
				case 7:		mpeg4_param->NumberBFrames			= 	atoi(param_line) - 1;	break;
				case 8:		mpeg4_param->SourceWidth			= 	atoi(param_line);	break;
				case 9:		mpeg4_param->SourceHeight			= 	atoi(param_line);	break;
				case 123:	mpeg4_param->TimeIncreamentRes		=   atoi(param_line);
							mpeg4_param->VopTimeIncreament		=   1;
							break;
				case 27:	*NumOfFrame		= 	atoi(param_line) + 1;	break;
				case 124:	mpeg4_param->Bitrate				= 	atoi(param_line);	break;
				case 42:	mpeg4_param->FrameQp				= 	atoi(param_line);	
							mpeg4_param->FrameQp_P = mpeg4_param->FrameQp+1;
							mpeg4_param->FrameQp_B = mpeg4_param->FrameQp+3;
							break;
				case 61:	mpeg4_param->DisableQpelME			= 	(!atoi(param_line))&0x01;	break;
				case 79:	mpeg4_param->IDRPeriod				= 	atoi(param_line);	break;
				case 96:	mpeg4_param->RandomIntraMBRefresh	= 	atoi(param_line);	break;

				case 114:	mpeg4_param->EnableFRMRateControl	= 	atoi(param_line);	break;
				case 116:	mpeg4_param->QSCodeMax				= 	atoi(param_line);	break;
				case 117:	mpeg4_param->QSCodeMin				= 	atoi(param_line);	break;
				case 118:	mpeg4_param->CBRPeriodRf			= 	atoi(param_line);	break;

				case 106:	ResyncEnable			= 	atoi(param_line) ;	break;
				case 107:	ResyncType				= 	atoi(param_line) ;	break;
				case 108:	SliceArgument1			= 	atoi(param_line) ;	break;
				case 109:	SliceArgument2			= 	atoi(param_line) ;	break;
			}			
		}while((param_line = strtok(NULL, "\r\n")) != NULL);

		if (ResyncEnable ==0 )
		{
			mpeg4_param->SliceMode			= 0;
			mpeg4_param->SliceArgument		= 0;
		}
		else if (ResyncType == 0) 
		{    
			mpeg4_param->SliceMode			= 1;
			mpeg4_param->SliceArgument		= SliceArgument1;
		}
		else
		{    
			mpeg4_param->SliceMode			= 2;
			mpeg4_param->SliceArgument		= SliceArgument2;
		}
		*width = mpeg4_param->SourceWidth;
		*height = mpeg4_param->SourceHeight;

		printf("inputFile : %s\n", inputFile);
		printf("NumOfFrame : %d\n", *NumOfFrame);
		printf("ProfileIDC : %d\n", mpeg4_param->ProfileIDC);
		printf("LevelIDC : %d\n", mpeg4_param->LevelIDC);
		printf("NumberBFrames : %d\n", mpeg4_param->NumberBFrames);
		printf("SourceWidth : %d\n", mpeg4_param->SourceWidth);
		printf("SourceHeight : %d\n", mpeg4_param->SourceHeight);
		printf("TimeIncreamentRes : %d\n", mpeg4_param->TimeIncreamentRes);
		printf("VopTimeIncreament : %d\n", mpeg4_param->VopTimeIncreament);
		printf("Bitrate : %d\n", mpeg4_param->Bitrate);
		printf("FrameQp : %d\n", mpeg4_param->FrameQp);
		printf("DisableQpelME : %d\n", mpeg4_param->DisableQpelME);
		printf("IDRPeriod : %d\n", mpeg4_param->IDRPeriod);
		printf("RandomIntraMBRefresh : %d\n", mpeg4_param->RandomIntraMBRefresh);
		printf("EnableFRMRateControl : %d\n", mpeg4_param->EnableFRMRateControl);
		printf("QSCodeMax : %d\n", mpeg4_param->QSCodeMax);
		printf("QSCodeMin : %d\n", mpeg4_param->QSCodeMin);
		printf("CBRPeriodRf : %d\n", mpeg4_param->CBRPeriodRf);
		printf("SliceMode : %d\n", mpeg4_param->SliceMode);
		printf("SliceArgument : %d\n", mpeg4_param->SliceArgument);
	}	
	else if (codec_type == H263_ENC)
	{
		char* ptemp;
		char* ptemp2;
		char* ptemp3;
		int j=0;
		SSBSIP_MFC_ENC_H263_PARAM *h263_param;
		int SourceResolution;

		printf("Parsing H263_ENC\n");
		h263_param = (SSBSIP_MFC_ENC_H263_PARAM *)encParam;
		h263_param->codecType = codec_type;		
		param_line = strtok(pConfigFileStr, "\r\n");

		do
		{
			if ((param_line[0] == '\n')||(param_line[0] == '\r'))
				continue;
				
			if(j == 5)
			{
				ptemp  = strchr(param_line, ' '); 
				if(ptemp != NULL) *ptemp = NULL;
				SourceResolution	= 	atoi(param_line) ;
				ptemp = ptemp + 1; 
				ptemp2  = strchr(ptemp, ' '); 
				if(ptemp2 != NULL) *ptemp2 = NULL;
				h263_param->SourceWidth		=     atoi(ptemp) ;
				ptemp2 = ptemp2+ 1; 
				ptemp3  = strchr(ptemp2, ' '); 
				if(ptemp3 != NULL) *ptemp3 = NULL;
				h263_param->SourceHeight		=     atoi(ptemp2) ;

			}
/*			else if(j == 0)
			{
				ptemp  = strchr(param_line, '\t');
				if(ptemp != NULL) *ptemp = NULL;

				ptemp2  = strchr(param_line, ':');
				if(ptemp2 != NULL) *ptemp = NULL;

			}
			*/
			else if(j != 0)
			{
				ptemp  = strchr(param_line, '\t');
				if(ptemp != NULL) *ptemp = NULL;

				ptemp2 = strchr(param_line, ' ');
				if(ptemp2 != NULL) *ptemp2 = NULL;
			}
			
			j++;

			switch(j)
			{
				case 1:		ptemp  = strchr(param_line, '.');
							ptemp2  = strchr(ptemp, ' ');
							if(ptemp2 != NULL) *ptemp2 = NULL;
							strcpy(inputFile, param_line);
							break;
				case 6:		SourceResolution		= 	atoi(param_line) ;	break;
				case 13:	h263_param->FrameRate				= 	atoi(param_line) ;	break;
				case 5:		*NumOfFrame		= 	atoi(param_line) ;	break;
				case 10:	h263_param->Bitrate					=   atoi(param_line) ;	break;
				case 8:		h263_param->FrameQp					= 	atoi(param_line) ;
							h263_param->FrameQp_P = h263_param->FrameQp+1;
							break;
				case 20:	h263_param->IDRPeriod				= 	atoi(param_line) ;	break;
				case 38:	h263_param->RandomIntraMBRefresh	= 	atoi(param_line) ;	break;
				case 16:	h263_param->SliceMode				= 	atoi(param_line) ;	break;
				case 47:	h263_param->EnableFRMRateControl	= 	atoi(param_line) ;	break;
				case 49:	h263_param->QSCodeMax				= 	atoi(param_line) ;	break;
				case 50:	h263_param->QSCodeMin				= 	atoi(param_line) ;	break;
				case 51:	h263_param->CBRPeriodRf				= 	atoi(param_line) ;	break;
			}
		}while((param_line = strtok(NULL, "\r\n")) != NULL);

		switch(SourceResolution)
		{
			case 1 :  
				h263_param->SourceWidth	= 128;
				h263_param->SourceHeight = 96 ;
				break;
			case 2 :	
				h263_param->SourceWidth	= 176;
				h263_param->SourceHeight	= 144 ;
				break;
			case 3 :
				h263_param->SourceWidth	= 352;
				h263_param->SourceHeight	= 288 ;
				break;
			case 4 :
				h263_param->SourceWidth	= 704;
				h263_param->SourceHeight	= 576 ;
				break;
			case 5 :
				h263_param->SourceWidth	= 1408;
				h263_param->SourceHeight	= 1152 ;
				break;
			case 6 :
				break;
			default :
				printf("image size format ERROR\n");
				break;
		}
		*width = h263_param->SourceWidth;
		*height = h263_param->SourceHeight;

		printf("inputFile : %s\n", inputFile);
		printf("NumOfFrame : %d\n", *NumOfFrame);
		printf("SourceWidth : %d\n", h263_param->SourceWidth);
		printf("SourceHeight : %d\n", h263_param->SourceHeight);
		printf("FrameRate : %d\n", h263_param->FrameRate);
		printf("Bitrate : %d\n", h263_param->Bitrate);
		printf("FrameQp : %d\n", h263_param->FrameQp);
		printf("IDRPeriod : %d\n", h263_param->IDRPeriod);
		printf("RandomIntraMBRefresh : %d\n", h263_param->RandomIntraMBRefresh);
		printf("EnableFRMRateControl : %d\n", h263_param->EnableFRMRateControl);
		printf("QSCodeMax : %d\n", h263_param->QSCodeMax);
		printf("QSCodeMin : %d\n", h263_param->QSCodeMin);
		printf("CBRPeriodRf : %d\n", h263_param->CBRPeriodRf);
		printf("SliceMode : %d\n", h263_param->SliceMode);

	}

	printf("Parsing Config File...END\n");
	
}

int MFCParseEncoderCFG(HANDLE *hFile, void *param, int *NumOfFrame, char *inputPath, char *outputPath, char *refPath,
					SSBSIP_MFC_CODEC_TYPE *codec_type, int *width, int *height)
{

	FILE*	fp_cfg;

	WIN32_FIND_DATA wfd;
	TCHAR sSearchMask[512];
	char CfgBuf[MAX_CFG_FILE_SIZE];
	char tmp[256];
	char *end, *type;
	int fileSize;

	//find  cfg file
	printf("MFCParseEncoderCFG\n");
	wsprintf(sSearchMask, TEXT("%s\\*.cfg"),ENCODER_CONFIG_PATH);
	wcstombs(tmp, sSearchMask, (int)wcslen(sSearchMask)+1);
	printf("%s\n", tmp);

	if( !*hFile ){
		if( (*hFile = FindFirstFile( sSearchMask, &wfd )) == INVALID_HANDLE_VALUE ){
			printf("No cfg file found\n");
			return 0;
		}
	}
	else{
		if( FindNextFile( *hFile, &wfd ) == 0 ){
			FindClose( *hFile );
			printf("No more cfg file found\n");
			return 0;
		}
	}

	wsprintf(sSearchMask, TEXT("%s\\%s"),ENCODER_CONFIG_PATH, wfd.cFileName);
	wcstombs(tmp, sSearchMask, (int)wcslen(sSearchMask)+1);
	printf("cfg file : %s\n", tmp);

	if( (fp_cfg=fopen(tmp, "rt"))==NULL )
	{
		printf("Cfg open error\n");
		return 0;
	}

	fileSize = fread(CfgBuf, 1, MAX_CFG_FILE_SIZE, fp_cfg);
	if(fileSize <= 0){
		printf("file read failed : %s\n", tmp);
		return 0;
	}

	if((type = strstr(tmp, ".h264.")) != NULL)
		*codec_type = H264_ENC;
	if((type = strstr(tmp, ".mpeg4.")) != NULL)
		*codec_type = MPEG4_ENC;
	if((type = strstr(tmp, ".h263.")) != NULL)
		*codec_type = H263_ENC;

	//Set output Path
	wcstombs(tmp, wfd.cFileName, (int)wcslen(wfd.cFileName)+1);
	end = strchr(tmp,'.');
	end[0] = NULL;
	if(*codec_type == MPEG4_ENC)
		strcat(tmp, ".m4v");
	else if(*codec_type == H263_ENC)
		strcat(tmp, ".263");
	else 
		strcat(tmp, ".264");

	sprintf(outputPath,"%s\\%s",ENCODER_OUTPUT_PATH, tmp);
	sprintf(refPath,"%s\\ref_%s",ENCODER_REF_PATH, tmp);

	MFC_ParseConfigFile(&CfgBuf[0], *codec_type, param, inputPath, NumOfFrame, width, height);

	fclose( fp_cfg );

	return 1;
}