/*
 * Project Name JPEG DRIVER IN WINCE
 * Copyright  2007 Samsung Electronics Co, Ltd. All Rights Reserved.
 *
 * This software is the confidential and proprietary information
 * of Samsung Electronics  ("Confidential Information").
 * you shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Samsung Electronics
 *
 * This file implements JPEG Test Application.
 *
 * @name JPEG Test Application Module (jpg_app.c)
 * @author Jiyoung Shin (idon.shin@samsung.com)
 * @date 28-05-07
 */
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "JPGApi.h"
#include "SVEDriverAPI.h"
#include "CAMDriver.h"


#define FPS       1


#define TEST_DECODE					1  // enable decoder test
#define TEST_DECODE_OUTPUT_FILE     1  // output file format : YCBYCR(interleaved), YV12
#define TEST_DECODE_OUTPUT_LCD      1  // output will display to LCD during DISPLAY_TIME

#define TEST_ENCODE					0 // enable encoder test
#define TEST_ENCODE_WITH_EXIF		1 // encoded jpg file will include Exif info
#define TEST_ENCODE_WITH_THUMBNAIL	1 // enable thumbnail encoding

#define CTRL_DEC_FILE_NAME	"\\Storage Card\\JPEG\\fname_dec.txt"
#define CTRL_ENC_FILE_NAME	"\\Storage Card\\JPEG\\fname_enc.txt"
#define STORAGE_NAME "\\Storage Card\\JPEG\\"

#define LCD_X		800
#define LCD_Y		480
#define DISPLAY_TIME	5   //sec

#define R_RGB565(x)		(unsigned char) (((x) >> 8) & 0xF8)
#define G_RGB565(x)		(unsigned char) (((x) >> 3) & 0xFC)
#define B_RGB565(x)		(unsigned char) ((x) << 3)

void TestDecoder();
void TestEncoder();
void DecodeFileOutYCBYCR(char *OutBuf, UINT32 streamSize, char *filename);
void DecodeFileOutYUV422(char *OutBuf, UINT32 streamSize, char *filename);
void DecodeFileOutNV12ToYV12(char *OutBuf, UINT32 streamSize, char *filename);
void makeExifParam(ExifFileInfo *exifFileInfo);
void DisplayJPEG (int srcAddr,int FrameBufferAddr,
				  INT32 srcwidth, INT32 srcheight,
				  INT32 dstwidth, INT32 dstheight,
				  int displayTime);
BOOL ConvertYCBYCRToRGB(int inBuf, INT32 srcwidth, INT32 srcheight,
						unsigned long srcType,
						int outBuf, INT32 dstwidth, INT32 dstheight,
						unsigned long dstType);
void DecodeFileOutRGB16ToPPM(unsigned char *p_img, int wd, int hi, char *filename);


/*
*******************************************************************************
Name            : main
Description     : Main function
Parameter       :
Return Value    : SUCCESS or FAILURE
*******************************************************************************
*/
int WINAPI WinMain(HINSTANCE hInstance,
					HINSTANCE hPrevInstance,
					LPTSTR    lpCmdLine,
					int       nCmdShow)
{
#if (TEST_DECODE == 1)
	TestDecoder();
#endif
#if (TEST_ENCODE == 1)
	TestEncoder();
#endif

	return 1;
}


/*
*******************************************************************************
Name            : TestDecoder
Description     : To test Decoder
Parameter       : imageType - JPG_YCBYCR or JPG_RGB16
Return Value    : void
*******************************************************************************
*/
void TestDecoder()
{
	char *InBuf = NULL;
	char *OutBuf = NULL;
	char *OutPhyBuf = NULL;
	char *OutRGBBuf = NULL;
	char *OutRGBPhyBuf = NULL;
	FILE *fp;
	FILE *CTRfp;
	UINT32 fileSize;
	UINT32 streamSize;
	void *handle;
	INT32 width, height, yuvwidth, yuvheight, samplemode;
	JPEG_ERRORTYPE ret;
	char outFilename[128];
	char inFilename[128];
	char outFilenameTmp[128];
	char inFilenameTmp[128];
	wchar_t wcs_outFilename[128];
	wchar_t wcs_inFilename[128];
	char outFormatstr[1];
	INT32 outFormat;
	BOOL result = TRUE;
#if (FPS == 1)
	INT32	decodeTime;
#endif
	DWORD	startTime;


	RETAILMSG(1, (_T("------------------------Decoder Test Start ---------------------\n")));

	//////////////////////////////////////////////////////////////
	// 0. Get input/output file name                            //
	//////////////////////////////////////////////////////////////
	CTRfp = fopen(CTRL_DEC_FILE_NAME, "rb");
	if(CTRfp == NULL){
		RETAILMSG(1, (_T("[JPGTest] file open error : %s\n"), CTRL_DEC_FILE_NAME));
		return;
	}

	do{
        memset(outFilename, 0x00, sizeof(outFilename));
        memset(inFilename, 0x00, sizeof(inFilename));
        memset(wcs_outFilename, 0x00, sizeof(wcs_outFilename));
        memset(wcs_inFilename, 0x00, sizeof(wcs_inFilename));
        memset(outFilenameTmp, 0x00, sizeof(outFilenameTmp));
        memset(inFilenameTmp, 0x00, sizeof(inFilenameTmp));
        memset(outFormatstr, 0x00, sizeof(outFormatstr));

		fscanf(CTRfp, "%s", inFilenameTmp);

		if(inFilenameTmp[0] == '#'){
			RETAILMSG(1, (_T("------------------------Decoder Test Done ---------------------\n")));
			fclose(CTRfp);
			return;
		}

		fscanf(CTRfp, "%s", outFilenameTmp);
		fscanf(CTRfp, "%s", outFormatstr);
        outFormat = (INT32)atoi(outFormatstr);

		if(inFilenameTmp[0] == 0 || outFilenameTmp[0] == 0)
		{
			RETAILMSG(1, (_T("[JPGTest] read file error\n")));
			RETAILMSG(1, (_T("------------------------Decoder Test Done ---------------------\n")));
			fclose(CTRfp);
			return;
		}

	    sprintf(inFilename, "%s%s", STORAGE_NAME, inFilenameTmp);
	    sprintf(outFilename, "%s%s", STORAGE_NAME, outFilenameTmp);
        mbstowcs(wcs_inFilename, inFilename, strlen(inFilename));
        mbstowcs(wcs_outFilename, outFilename, strlen(outFilename));

        RETAILMSG(1, (_T("\n-------------------------------------------------------------\n")));
		RETAILMSG(1, (_T("inFilename : %s \noutFilename : %s\n"), wcs_inFilename, wcs_outFilename));
        RETAILMSG(1, (_T("\n-------------------------------------------------------------\n")));
		
		//////////////////////////////////////////////////////////////
		// 1. handle Init                                           //
		//////////////////////////////////////////////////////////////
		#if (FPS == 1)
			decodeTime = GetTickCount();
		#endif
		handle = SsbSipJPEGDecodeInit();
		#if (FPS == 1)
			decodeTime = GetTickCount() - decodeTime;
			RETAILMSG(1, (_T( "[JPGTest] Initialization Time : %d \n"), decodeTime));
		#endif
		if(handle == NULL)
		{
			RETAILMSG(1, (_T("[JPGTest] Decoder Init failed\n")));
			break;
		}

		//////////////////////////////////////////////////////////////
		// 2. open JPEG file to decode                              //
		//////////////////////////////////////////////////////////////
		fp = fopen(inFilename, "rb");
		if(fp == NULL)
		{
			result = FALSE;
			RETAILMSG(1, (_T("[JPGTest] file open error : %s\n"), inFilename));
			break;
		}
		fseek(fp, 0, SEEK_END);
		fileSize = ftell(fp);
		fseek(fp, 0, SEEK_SET);

		//////////////////////////////////////////////////////////////
		// 3. get Input buffer                              //
		//////////////////////////////////////////////////////////////
		InBuf = SsbSipJPEGGetDecodeInBuf(handle, fileSize);
		if(InBuf == NULL)
		{
			RETAILMSG(1, (_T("[JPGTest] Input buffer is NULL\n")));
			result = FALSE;
			fclose(fp);
			break;
		}


		//////////////////////////////////////////////////////////////
		// 4. put JPEG frame to Input buffer                        //
		//////////////////////////////////////////////////////////////
		fread(InBuf, 1, fileSize, fp);
		fclose(fp);

		//////////////////////////////////////////////////////////////
		// 5. set decode config.                                    //
		//////////////////////////////////////////////////////////////
		if((ret = SsbSipJPEGSetConfig(handle, JPEG_SET_DECODE_OUT_FORMAT, outFormat)) != JPEG_OK)
		{
			result = FALSE;
			continue;
		}

        //////////////////////////////////////////////////////////////
		// 6. Decode JPEG frame                                     //
		//////////////////////////////////////////////////////////////
		#if (FPS == 1)
			decodeTime = GetTickCount();
		#endif

		ret = SsbSipJPEGDecodeExe(handle);

		#if (FPS == 1)
			decodeTime = GetTickCount() - decodeTime;
			RETAILMSG(1, (_T( "[JPGTest] decodeTime : %d \n"), decodeTime));
		#endif

		if(ret != JPEG_OK)
		{
			RETAILMSG(1, (_T("[JPGTest] Decoding failed\n")));
			result = FALSE;
			break;
		}

		//////////////////////////////////////////////////////////////
		// 7. get Output buffer address                             //
		//////////////////////////////////////////////////////////////
		OutBuf = SsbSipJPEGGetDecodeOutBuf(handle, &streamSize);
		if(OutBuf == NULL)
		{
			RETAILMSG(1, (_T("[JPGTest] Output buffer is NULL\n")));
			result = FALSE;
			break;
		}

		//////////////////////////////////////////////////////////////
		// 7. get decode config.                                    //
		//////////////////////////////////////////////////////////////
		SsbSipJPEGGetConfig(handle, JPEG_GET_DECODE_WIDTH, &width);
		SsbSipJPEGGetConfig(handle, JPEG_GET_DECODE_HEIGHT, &height);
		SsbSipJPEGGetConfig(handle, JPEG_GET_DECODE_YUV_WIDTH, &yuvwidth);
		SsbSipJPEGGetConfig(handle, JPEG_GET_DECODE_YUV_HEIGHT, &yuvheight);
		SsbSipJPEGGetConfig(handle, JPEG_GET_SAMPING_MODE, &samplemode);

		RETAILMSG(1, (_T("[JPGTest] orgwidth : %d orgheight : %d yuvwidth : %d yuvheight : %d samplemode : %d\n\n"),
                width, height, yuvwidth, yuvheight, samplemode));

		//////////////////////////////////////////////////////////////
		// 8. wirte output file                                     //
		//////////////////////////////////////////////////////////////

        switch(outFormat) {
            case YCBCR_422:
#if (TEST_DECODE_OUTPUT_FILE == 1)
        		DecodeFileOutYCBYCR(OutBuf, streamSize, outFilename);	// YCBYCR interleaved
#endif

#if(TEST_DECODE_OUTPUT_LCD == 1)

        		OutPhyBuf = SsbSipJPEGGetDecodeOutPhyBuf(handle);
        		OutRGBPhyBuf = SsbSipJPEGGetRGBPhyBuf(handle, LCD_X, LCD_Y);
	
        		DisplayJPEG((int)OutPhyBuf, (int)OutRGBPhyBuf, yuvwidth, yuvheight, LCD_X, LCD_Y, DISPLAY_TIME);

#endif
                break;
            case YCBCR_420:
#if (TEST_DECODE_OUTPUT_FILE == 1)
                DecodeFileOutNV12ToYV12(OutBuf, streamSize, outFilename);   // Convert JPEG H/W NV12 output to YV12
#endif
                break;
            default:
                RETAILMSG(1, (_T("[JPGTest] Not supported output format\n")));
                break;
        }

		//////////////////////////////////////////////////////////////
		// 9. finalize handle                                      //
		//////////////////////////////////////////////////////////////
		SsbSipJPEGDecodeDeInit(handle);
		Sleep(5);
	}while(1);

	if(result == FALSE){
		SsbSipJPEGDecodeDeInit(handle);
	}

    fclose(CTRfp);
    RETAILMSG(1, (_T("------------------------Decoder Test Done ---------------------\n")));
}


/*
*******************************************************************************
Name            : TestEncoder
Description     : To test Encoder
Parameter       : imageType - JPG_YCBYCR or JPG_RGB16
Return Value    : void
*******************************************************************************
*/
void TestEncoder()
{
	char *InBuf = NULL;
	char *InThumbBuf = NULL;
	char *OutBuf = NULL;
	FILE *fp;
	FILE *CTRfp;
	JPEG_ERRORTYPE ret;
	UINT32 fileSize;
	UINT32 frameSize;
	void *handle;
	ExifFileInfo *ExifInfo = NULL;
	char outFilename[128];
	char inFilename[128];
	char outFilenameTmp[128];
	char inFilenameTmp[128];
    wchar_t wcs_outFilename[128];
    wchar_t wcs_inFilename[128];
	char widthstr[8], heightstr[8];
    char inFormatstr[1];
    char sampleingModestr[1];
    char mode_y16str[1];
	INT32 width, height, inFormat, samplingMode, mode_y16;
	BOOL result = TRUE;
#if (FPS == 1)
	INT32	encodeTime;
#endif

	RETAILMSG(1, (_T("------------------------Encoder Test start---------------------\n")));
	//////////////////////////////////////////////////////////////
	// 0. Get input/output file name                            //
	//////////////////////////////////////////////////////////////
	CTRfp = fopen(CTRL_ENC_FILE_NAME, "rb");
	if(CTRfp == NULL){
		RETAILMSG(1, (_T("[JPGTest] file open error : %s\n"), CTRL_ENC_FILE_NAME));
		return;
	}

	do{
		memset(outFilename, 0x00, sizeof(outFilename));
		memset(inFilename, 0x00, sizeof(inFilename));
        memset(wcs_outFilename, 0x00, sizeof(wcs_outFilename));
        memset(wcs_inFilename, 0x00, sizeof(wcs_inFilename));
		memset(outFilenameTmp, 0x00, sizeof(outFilenameTmp));
		memset(inFilenameTmp, 0x00, sizeof(inFilenameTmp));
		memset(widthstr, 0x00, sizeof(widthstr));
		memset(heightstr, 0x00, sizeof(heightstr));
		memset(inFormatstr, 0x00, sizeof(inFormatstr));
		memset(sampleingModestr, 0x00, sizeof(sampleingModestr));
		memset(mode_y16str, 0x00, sizeof(mode_y16str));

		fscanf(CTRfp, "%s", inFilenameTmp);
		if(inFilenameTmp[0] == '#'){
			RETAILMSG(1, (_T("------------------------Encoder Test Done---------------------\n")));
			fclose(CTRfp);
			return;
		}

		fscanf(CTRfp, "%s", outFilenameTmp);
		fscanf(CTRfp, "%s", widthstr);
		fscanf(CTRfp, "%s", heightstr);
		fscanf(CTRfp, "%s", inFormatstr);
		fscanf(CTRfp, "%s", sampleingModestr);
		fscanf(CTRfp, "%s", mode_y16str);
		width = (INT32)atoi(widthstr);
		height = (INT32)atoi(heightstr);
        inFormat = (INT32)atoi(inFormatstr);
        samplingMode = (INT32)atoi(sampleingModestr);
        mode_y16 = (INT32)atoi(mode_y16str);
		if(inFilenameTmp[0] == 0 || outFilenameTmp[0] == 0){
			RETAILMSG(1, (_T("[JPGTest] read file error\n")));
			RETAILMSG(1, (_T("------------------------Encoder Test Done---------------------\n")));
			fclose(CTRfp);
			return;
		}

	    sprintf(inFilename, "%s%s", STORAGE_NAME, inFilenameTmp);
	    sprintf(outFilename, "%s%s", STORAGE_NAME, outFilenameTmp);
        mbstowcs(wcs_inFilename, inFilename, strlen(inFilename));
        mbstowcs(wcs_outFilename, outFilename, strlen(outFilename));

        RETAILMSG(1, (_T("\n-----------------------------------------------------------------\n")));
        RETAILMSG(1, (_T("inFilename : %s \noutFilename : %s width : %d height : %d\n"),
				wcs_inFilename, wcs_outFilename, width, height));
        RETAILMSG(1, (_T("\n-----------------------------------------------------------------\n")));
		//////////////////////////////////////////////////////////////
		// 1. handle Init                                           //
		//////////////////////////////////////////////////////////////
		#if (FPS == 1)
			encodeTime = GetTickCount();
		#endif
		handle = SsbSipJPEGEncodeInit();
		#if (FPS == 1)
			encodeTime = GetTickCount() - encodeTime;
			RETAILMSG(1, (_T( "[JPGTest] Initialization Time : %d \n"), encodeTime));
		#endif
		if(handle == NULL)
			break;

		//////////////////////////////////////////////////////////////
		// 2. set encode config.                                    //
		//////////////////////////////////////////////////////////////
		if((ret = SsbSipJPEGSetConfig(handle, JPEG_SET_ENCODE_IN_FORMAT, inFormat)) != JPEG_OK){
			result = FALSE;
			break;
		}
        if((ret = SsbSipJPEGSetConfig(handle, JPEG_SET_SAMPING_MODE, samplingMode)) != JPEG_OK){
			result = FALSE;
			break;
		}
		if((ret = SsbSipJPEGSetConfig(handle, JPEG_SET_ENCODE_WIDTH, width)) != JPEG_OK){
			result = FALSE;
			break;
		}
		if((ret = SsbSipJPEGSetConfig(handle, JPEG_SET_ENCODE_HEIGHT, height)) != JPEG_OK){
			result = FALSE;
			break;
		}
		if((ret = SsbSipJPEGSetConfig(handle, JPEG_SET_ENCODE_QUALITY, JPG_QUALITY_LEVEL_2)) != JPEG_OK){
			result = FALSE;
			break;
		}
		if((ret = SsbSipJPEGSetConfig(handle, JPEG_SET_ENCODE_Y16, mode_y16)) != JPEG_OK){
			result = FALSE;
			break;
		}
#if (TEST_ENCODE_WITH_THUMBNAIL == 1)
		if((ret = SsbSipJPEGSetConfig(handle, JPEG_SET_ENCODE_THUMBNAIL, TRUE)) != JPEG_OK){
			result = FALSE;
			break;
		}
		if((ret = SsbSipJPEGSetConfig(handle, JPEG_SET_THUMBNAIL_WIDTH, 160)) != JPEG_OK){
			result = FALSE;
			break;
		}
		if((ret = SsbSipJPEGSetConfig(handle, JPEG_SET_THUMBNAIL_HEIGHT, 120)) != JPEG_OK){
			result = FALSE;
			break;
		}
#endif

		//////////////////////////////////////////////////////////////
		// 3. open YUV file to encode                              //
		//////////////////////////////////////////////////////////////
		fp = fopen(inFilename, "rb");
		if(fp == NULL){
			RETAILMSG(1, (_T("[JPGTest] file open error : %s\n"), inFilename));
			result = FALSE;
			break;
		}
		fseek(fp, 0, SEEK_END);
		fileSize = ftell(fp);
		fseek(fp, 0, SEEK_SET);

		//////////////////////////////////////////////////////////////
		// 4. get Input buffer address                              //
		//////////////////////////////////////////////////////////////
		InBuf = SsbSipJPEGGetEncodeInBuf(handle, fileSize);
		if(InBuf == NULL){
			result = FALSE;
    		fclose(fp);
			break;
		}

		//////////////////////////////////////////////////////////////
		// 5. put YUV stream to Input buffer                        //
		//////////////////////////////////////////////////////////////
		fread(InBuf, 1, fileSize, fp);
		fclose(fp);


		//////////////////////////////////////////////////////////////
		// 6. Make Exif info parameters                             //
		//////////////////////////////////////////////////////////////
		ExifInfo = (ExifFileInfo *)malloc(sizeof(ExifFileInfo));
		if(!ExifInfo) {
			result = FALSE;
			break;
		}
		memset(ExifInfo, 0x00, sizeof(ExifFileInfo));
		makeExifParam(ExifInfo);

		//////////////////////////////////////////////////////////////
		// 7. Encode YUV stream                                     //
		//////////////////////////////////////////////////////////////
		#if (FPS == 1)
			encodeTime = GetTickCount();
		#endif

		#if (TEST_ENCODE_WITH_EXIF == 1)
		ret = SsbSipJPEGEncodeExe(handle, ExifInfo);    //with Exif
		#else
		ret = SsbSipJPEGEncodeExe(handle, NULL); 		//No Exif
		#endif

		#if (FPS == 1)
			encodeTime = GetTickCount() - encodeTime;
			RETAILMSG(1, (_T( "encodeTime : %d \n"), encodeTime));
		#endif
		if(ret != JPEG_OK){
			result = FALSE;
			break;
		}

		//////////////////////////////////////////////////////////////
		// 8. get output buffer address                             //
		//////////////////////////////////////////////////////////////
		OutBuf = SsbSipJPEGGetEncodeOutBuf(handle, &frameSize);
		if(OutBuf == NULL){
			result = FALSE;
			break;
		}


		//////////////////////////////////////////////////////////////
		// 9. write JPEG result file                                //
		//////////////////////////////////////////////////////////////
		fp = fopen(outFilename, "wb");
		if(fp == NULL){
			RETAILMSG(1, (_T("[JPGTest] fopen error[%s]\n"), outFilename));
			result = FALSE;
			break;
		}
		fwrite(OutBuf, 1, frameSize, fp);
		fclose(fp);

		//////////////////////////////////////////////////////////////
		// 10. finalize handle                                      //
		//////////////////////////////////////////////////////////////
		SsbSipJPEGEncodeDeInit(handle);
		free(ExifInfo);
		Sleep(5);
	}while(1);

	if(result == FALSE){
		SsbSipJPEGEncodeDeInit(handle);
		if(ExifInfo != NULL)
			free(ExifInfo);
	}
	fclose(CTRfp);
	RETAILMSG(1, (_T("------------------------Encoder Test Done---------------------\n")));
}


/*
*******************************************************************************
Name            : makeExifParam
Description     : To make exif input parameter
Parameter       :
Return Value    : exifFileInfo - exif input parameter
*******************************************************************************
*/
void makeExifParam(ExifFileInfo *exifFileInfo)
{
	strcpy(exifFileInfo->Make,"Samsung SYS.LSI make");;
	strcpy(exifFileInfo->Model,"Samsung 2009 model");
	strcpy(exifFileInfo->Version,"version 1.2.0");
	strcpy(exifFileInfo->DateTime,"2007:05:16 12:32:54");
	strcpy(exifFileInfo->CopyRight,"Samsung Electronics");
        //19: julie.kwon-CopyRight's size is 32. but former data is longer than 32byts.

	exifFileInfo->Height					= 320;
	exifFileInfo->Width						= 240;
	exifFileInfo->Orientation				= 1; // top-left
	exifFileInfo->ColorSpace				= 1;
	exifFileInfo->Process					= 1;
	exifFileInfo->Flash						= 0;
	exifFileInfo->FocalLengthNum			= 1;
	exifFileInfo->FocalLengthDen			= 4;
	exifFileInfo->ExposureTimeNum			= 1;
	exifFileInfo->ExposureTimeDen			= 20;
	exifFileInfo->FNumberNum				= 1;
	exifFileInfo->FNumberDen				= 35;
	exifFileInfo->ApertureFNumber			= 1;
	exifFileInfo->SubjectDistanceNum		= -20;
	exifFileInfo->SubjectDistanceDen		= -7;
	exifFileInfo->CCDWidth					= 1;
	exifFileInfo->ExposureBiasNum			= -16;
	exifFileInfo->ExposureBiasDen			= -2;
	exifFileInfo->WhiteBalance				= 6;
	exifFileInfo->MeteringMode				= 3;
	exifFileInfo->ExposureProgram			= 1;
	exifFileInfo->ISOSpeedRatings[0]		= 1;
	exifFileInfo->ISOSpeedRatings[1]		= 2;
	exifFileInfo->FocalPlaneXResolutionNum	= 65;
	exifFileInfo->FocalPlaneXResolutionDen	= 66;
	exifFileInfo->FocalPlaneYResolutionNum	= 70;
	exifFileInfo->FocalPlaneYResolutionDen	= 71;
	exifFileInfo->FocalPlaneResolutionUnit	= 3;
	exifFileInfo->XResolutionNum			= 48;
	exifFileInfo->XResolutionDen			= 20;
	exifFileInfo->YResolutionNum			= 48;
	exifFileInfo->YResolutionDen			= 20;
	exifFileInfo->RUnit						= 2;
	exifFileInfo->BrightnessNum				= -7;
	exifFileInfo->BrightnessDen				= 1;

	strcpy(exifFileInfo->UserComments,"Usercomments");
}


/*
*******************************************************************************
Name            : DecodeFileOutYUV422
Description     : To change YCBYCR to YUV422, and write result file.
Parameter       :
Return Value    : void
*******************************************************************************
*/
void DecodeFileOutYUV422(char *OutBuf, UINT32 streamSize, char *filename)
{
	UINT32	i;
	UINT32  indexY, indexCB, indexCR;
	char *Buf;
	FILE *fp;

	Buf = (char *)malloc(MAX_YUV_SIZE);
	memset(Buf, 0x00, MAX_YUV_SIZE);

	RETAILMSG(1, (_T("[JPGTest] convertyuvformat\n")));
	indexY = 0;
	indexCB = streamSize >> 1;
	indexCR = indexCB+(streamSize >> 2);

	RETAILMSG(0, (_T("[JPGTest] streamSize(%d), indexY(%ld), indexCB(%ld), indexCR(%ld)\n"), streamSize, indexY, indexCB, indexCR));

	for(i = 0; i < streamSize; i++)
	{
		if((i%2) == 0)
			Buf[indexY++] = OutBuf[i];

		if((i%4) == 1)
			Buf[indexCB++] = OutBuf[i];

		if((i%4) == 3)
			Buf[indexCR++] = OutBuf[i];
	}

	fp = fopen(filename, "wb");
	if(fp == NULL){
		RETAILMSG(1, (_T("[JPGTest] fopen error[%s]\n"), filename));
    	free(Buf);
		return;
	}
	fwrite(Buf, 1, streamSize, fp);
	fclose(fp);
	free(Buf);
}


/*
*******************************************************************************
Name            : DecodeFileOutYCBYCR
Description     : To write result YCBYCR file.
Parameter       :
Return Value    : void
*******************************************************************************
*/
void DecodeFileOutYCBYCR(char *OutBuf, UINT32 streamSize, char *filename)
{
	FILE *fp;

	fp = fopen(filename, "wb");
	if(fp == NULL){
		RETAILMSG(1, (_T("[JPGTest] fopen error[%s]\n"), filename));
		return;
	}
	fwrite(OutBuf, 1, streamSize, fp);
	fclose(fp);
}


/*
*******************************************************************************
Name            : DecodeFileOutNV12ToYV12
Description     : To write result NV12 to YV12 file.
Parameter       :
Return Value    : void
*******************************************************************************
*/
void DecodeFileOutNV12ToYV12(char *OutBuf, UINT32 streamSize, char *filename)
{
	FILE *fp;
    unsigned char *Buf;
    int indexCr, indexCb;
    UINT32 i;

	Buf = (unsigned char *)malloc(streamSize);
	memset(Buf, 0x00, streamSize);

    // Copy Y
    memcpy(Buf, OutBuf, streamSize*2/3);

    // Copy Cb, Cr
	indexCr = streamSize*2/3;
	indexCb = indexCr+streamSize/6;


    RETAILMSG(0, (_T("[JPGTest] DecodeFileOutNV12ToYV12++: streamSize=%d, indexCr=%d, idexCb=%d\n"), streamSize, indexCr, indexCb));

    for(i = indexCr; i < streamSize; i+=2)
	{
		Buf[indexCb++] = OutBuf[i];
		Buf[indexCr++] = OutBuf[i+1];
	}

    RETAILMSG(0, (_T("[JPGTest] DecodeFileOutNV12ToYV12--: streamSize=%d, indexCr=%d, idexCb=%d, i=%d\n"), streamSize, indexCr, indexCb, i));

	fp = fopen(filename, "wb");
	if(fp == NULL){
		RETAILMSG(1, (_T("[JPGTest] fopen error[%s]\n"), filename));
    	free(Buf);
		return;
	}
	fwrite(Buf, 1, streamSize, fp);
	fclose(fp);
	free(Buf);
}


/*
*******************************************************************************
Name            : DecodeFileOutYCBYCR
Description     : To write result YCBYCR file.
Parameter       :
Return Value    : void
*******************************************************************************
*/
void DisplayJPEG (int srcAddr,int FrameBufferAddr,
				  INT32 srcwidth, INT32 srcheight,
				  INT32 dstwidth, INT32 dstheight,
				  int displayTime)
{
	HANDLE						hVideoDrv = INVALID_HANDLE_VALUE;
	SVEARG_FIMD_WIN_MODE		tParamMode;
	SVEARG_FIMD_WIN_FRAMEBUFFER tParamFB;
	SVEARG_FIMD_WIN_ALPHA		tParamAlpha;
	SVEARG_POST_PARAMETER		tParamPost;
	SVEARG_POST_BUFFER			tParamBuffer;
	DWORD						dwWinNum;
	DWORD						dwBytes;

	//-----------------------
	// Open Video Driver
	//-----------------------
	hVideoDrv = CreateFile( L"VDE0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
	if (hVideoDrv == INVALID_HANDLE_VALUE)
	{
		RETAILMSG(1,(L"[VDE:ERR] VDE0 Open Device Failed\n"));
		return;
	}

	// Request FIMD Win0 H/W Resource to Video Engine Driver for Local Path
	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_RSC_REQUEST_FIMD_WIN1, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_REQUEST_FIMD_WIN1 Failed\n"));
		return;
	}
	
	// Request Post Processor H/W Resource to Video Engine Driver for Local Path
	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_RSC_REQUEST_POST, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_REQUEST_POST Failed\n"));
		return;
	}
	
	tParamMode.dwWinMode = DISP_WIN1_DMA;
	tParamMode.dwBPP = DISP_16BPP_565;
	tParamMode.dwWidth = LCD_X;
	tParamMode.dwHeight = LCD_Y;
	tParamMode.dwOffsetX = 0;
	tParamMode.dwOffsetY = 0;

	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_FIMD_SET_WINDOW_MODE, &tParamMode, sizeof(SVEARG_FIMD_WIN_MODE), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_FIMD_SET_WINDOW_MODE Failed\n"));
		return;
	}

	tParamAlpha.dwWinNum = DISP_WIN2;
	tParamAlpha.dwMethod = DISP_ALPHA_PER_PLANE;
	tParamAlpha.dwAlpha0 = 0x0;
	tParamAlpha.dwAlpha1 = 0x0;
	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_FIMD_SET_WINDOW_BLEND_ALPHA, &tParamAlpha, sizeof(SVEARG_FIMD_WIN_ALPHA), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_FIMD_SET_WINDOW_BLEND_ALPHA Failed\n"));
	}

	// Set Window1 Framebuffer
	tParamFB.dwWinNum = DISP_WIN1;
	tParamFB.dwFrameBuffer = FrameBufferAddr;
	tParamFB.bWaitForVSync = FALSE;
	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_FIMD_SET_WINDOW_FRAMEBUFFER, &tParamFB, sizeof(SVEARG_FIMD_WIN_FRAMEBUFFER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_FIMD_SET_WINDOW_FRAMEBUFFER Failed\n"));
		return;
	}

	// Window0 Enable
	dwWinNum = DISP_WIN1;
	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_FIMD_SET_WINDOW_ENABLE, &dwWinNum, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_FIMD_SET_WINDOW_ENABLE Failed\n"));
		return;
	}

	tParamPost.dwOpMode = POST_PER_FRAME_MODE;
	tParamPost.dwScanMode = POST_PROGRESSIVE;
	tParamPost.dwSrcType = POST_SRC_YUV422_CRYCBY;
	tParamPost.dwRotFlipMode = MAKELONG(POST_0_NOFLIP, POST_0_NOFLIP);
	tParamPost.dwDMATileMode = MAKELONG(POST_DMA_LINEAR, POST_DMA_LINEAR);
 	tParamPost.dwSrcBaseWidth = srcwidth;
	tParamPost.dwSrcBaseHeight = srcheight;
	tParamPost.dwSrcOffsetX = 0;
	tParamPost.dwSrcOffsetY = 0;
	tParamPost.dwSrcWidth = srcwidth;
	tParamPost.dwSrcHeight = srcheight ;
	tParamPost.dwDstType = POST_DST_RGB16;
 	tParamPost.dwDstBaseWidth = LCD_X;
	tParamPost.dwDstBaseHeight = LCD_Y;
	tParamPost.dwDstWidth = LCD_X;
	tParamPost.dwDstHeight = LCD_Y;
	tParamPost.dwDstOffsetX = (tParamPost.dwDstBaseWidth - tParamPost.dwDstWidth)/2;
	tParamPost.dwDstOffsetY = (tParamPost.dwDstBaseHeight - tParamPost.dwDstHeight)/2;



	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_POST_SET_PROCESSING_PARAM, &tParamPost, sizeof(SVEARG_POST_PARAMETER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_PROCESSING_PARAM Failed\n"));
		return;
	}

	tParamBuffer.dwBufferRGBY =srcAddr;
	tParamBuffer.dwBufferCb = 0;
	tParamBuffer.dwBufferCr = 0;
	tParamBuffer.bWaitForVSync = FALSE;

	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_POST_SET_SOURCE_BUFFER, &tParamBuffer, sizeof(SVEARG_POST_BUFFER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_SOURCE_BUFFER Failed\n"));
		return;
	}

	// Destination Address
	tParamBuffer.dwBufferRGBY = FrameBufferAddr;
	tParamBuffer.dwBufferCb = 0;
	tParamBuffer.dwBufferCr = 0;
	tParamBuffer.bWaitForVSync = FALSE;

	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_POST_SET_DESTINATION_BUFFER, &tParamBuffer, sizeof(SVEARG_POST_BUFFER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_DESTINATION_BUFFER Failed\n"));
		return;
	}

	// Post Processing Start
	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_POST_SET_PROCESSING_START, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_PROCESSING_START Failed\n"));
		return;
	}
			

	Sleep(displayTime*1000);

	//--------------------------------------------
	// close surface
	//---------------------------------------------

	dwWinNum = DISP_WIN1;
	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_POST_SET_PROCESSING_STOP, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_PROCESSING_STOP Failed\n"));
		return;
	}

	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_FIMD_SET_WINDOW_DISABLE, &dwWinNum, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_FIMD_SET_WINDOW_DISABLE Failed\n"));
		return;
	}	

	// Release FIMD Win0 H/W Resource to Video Engine Driver for Local Path
	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_RSC_RELEASE_FIMD_WIN1, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_RELEASE_FIMD_WIN1 Failed\n"));
		return;
	}

	// Release Post Processor H/W Resource to Video Engine Driver for Local Path
	if ( !DeviceIoControl(hVideoDrv, IOCTL_SVE_RSC_RELEASE_POST, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_RELEASE_POST Failed\n"));
		return;
	}

	CloseHandle(hVideoDrv);


}


BOOL ConvertYCBYCRToRGB(int inBuf, INT32 srcwidth, INT32 srcheight,
						unsigned long srcType,
						int outBuf, INT32 dstwidth, INT32 dstheight,
						unsigned long dstType)
{
	HANDLE hPostDrv = INVALID_HANDLE_VALUE;
	SVEARG_POST_PARAMETER tParamPost;
	SVEARG_POST_BUFFER tParamBuffer;
	DWORD dwBytes;

	hPostDrv = CreateFile( L"VDE0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
	if (hPostDrv == INVALID_HANDLE_VALUE)
	{
		RETAILMSG(1,(L"[VDE:ERR] VDE0 Open Device Failed\n"));
		return FALSE;
	}

	// Request Post Processor H/W Resource to Video Engine Driver for Local Path
	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_RSC_REQUEST_POST, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_REQUEST_POST Failed\n"));
		return	FALSE;
	}

	tParamPost.dwOpMode = POST_PER_FRAME_MODE;
	tParamPost.dwScanMode = POST_PROGRESSIVE;
	tParamPost.dwSrcType = srcType;
	tParamPost.dwSrcBaseWidth = srcwidth;
	tParamPost.dwSrcBaseHeight = srcheight;
	tParamPost.dwSrcWidth = srcwidth;
	tParamPost.dwSrcHeight = srcheight;
	tParamPost.dwSrcOffsetX = 0;
	tParamPost.dwSrcOffsetY = 0;
	tParamPost.dwDstType = dstType;
	tParamPost.dwDstBaseWidth = dstwidth;
	tParamPost.dwDstBaseHeight = dstheight;
	tParamPost.dwDstWidth = dstwidth;
	tParamPost.dwDstHeight = dstheight;
	tParamPost.dwDstOffsetX = 0;
	tParamPost.dwDstOffsetY = 0;

	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_POST_SET_PROCESSING_PARAM, &tParamPost, sizeof(SVEARG_POST_PARAMETER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_PROCESSING_PARAM Failed\n"));
		return FALSE;
	}

	// Source Address
	tParamBuffer.dwBufferRGBY = (DWORD)inBuf;
	tParamBuffer.dwBufferCb = tParamBuffer.dwBufferRGBY+srcwidth*srcheight;
	tParamBuffer.dwBufferCr = tParamBuffer.dwBufferCb+srcwidth*srcheight/4;
	tParamBuffer.bWaitForVSync = FALSE;

	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_POST_SET_SOURCE_BUFFER, &tParamBuffer, sizeof(SVEARG_POST_BUFFER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_SOURCE_BUFFER Failed\n"));
		return FALSE;
	}

	// Destination Address
	tParamBuffer.dwBufferRGBY = (DWORD)outBuf;
	tParamBuffer.dwBufferCb = 0;
	tParamBuffer.dwBufferCr = 0;
	tParamBuffer.bWaitForVSync = FALSE;

	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_POST_SET_DESTINATION_BUFFER, &tParamBuffer, sizeof(SVEARG_POST_BUFFER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_DESTINATION_BUFFER Failed\n"));
		return FALSE;
	}

	// Post Processing Start
	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_POST_SET_PROCESSING_START, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_PROCESSING_START Failed\n"));
		return FALSE;
	}

	// Wait for Post Processing Finished
	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_POST_WAIT_PROCESSING_DONE, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_WAIT_PROCESSING_DONE Failed\n"));
		return FALSE;
	}

	// Release Post Processor H/W Resource to Video Engine Driver for Local Path
	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_RSC_RELEASE_POST, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_RELEASE_POST Failed\n"));
		return FALSE;
	}

	CloseHandle(hPostDrv);

	return TRUE;


}


/*
*******************************************************************************
Name            : DecodeFileOutRGB16ToPPM
Description     : To change RGB16 to PPM, and write result file.
Parameter       :
Return Value    : void
*******************************************************************************
*/
void DecodeFileOutRGB16ToPPM(unsigned char *p_img, int wd, int hi,  char *filename)
{
	int   i, size;
	FILE *fp_write = NULL;
	unsigned short rgb565;
	unsigned char  rgb[3];

	fp_write = fopen(filename, "wb");
	if(fp_write == NULL){
		RETAILMSG(1, (_T("[JPGTest] fopen error[%s]\n"), filename));
		return;
	}

	fprintf(fp_write, "P6\n");
	fprintf(fp_write, "# Samsung Electronics\n");
	fprintf(fp_write, "%d %d\n255\n", wd, hi);

	size = wd * hi;
	for (i=0; i<size; i++) {
		rgb565 = (*p_img) | (*(++p_img));
		rgb[0] = *p_img++;
		rgb[1] = *p_img;
		rgb565 = (rgb[0]<<8) | rgb[1];

		rgb[0] = R_RGB565(rgb565);
		rgb[1] = G_RGB565(rgb565);
		rgb[2] = B_RGB565(rgb565);

		fwrite(rgb, 1, 3, fp_write);
	}

	fclose(fp_write);
}
