/*****************************************************************************
Copyright(c) 2005 Analog Devices, Inc.  All Rights Reserved. This software is 
proprietary and confidential to Analog Devices, Inc. and its licensors.
******************************************************************************

$RCSfile: jpeg_decode.c,v $
$Revision: 1.3 $
$Date: 2008/06/06 06:01:18 $

Project:	BlackfinSDK (JPEG)
Title:		JPEG decode
Author(s):	
Revised by: 

Description:
			High level JPEG decoding functions

References:
			None

******************************************************************************
Tab Setting:			4

Target Processor:		ADSP-BF5xx
Target Tools Revision:	ADSP VisualDSP++ v4.5
******************************************************************************

Modification History:
====================
$Log: jpeg_decode.c,v $
Revision 1.3  2008/06/06 06:01:18  randreol
Changes to allow for Kookaburra port

Revision 1.2  2008/03/25 05:42:25  randreol
Added memory sections for NO_INIT


*****************************************************************************/

#include <stdio.h>					
#include <string.h>				
#include <stdlib.h>

#include <drivers/adi_dev.h>	

#include <JPEG_api_decoder.h>
#include <JPEG_BitsBuffer.h>
#include <jpeg_mjpeg_err.h>
#include <drivers/pixc/adi_pixc.h>          	/* Pixel Compositor driver includes */
#include "adi_ssl_init.h"	            

#if defined(__ADSP_MOAB__) | defined(__ADSP_KOOKABURRA__)
#include "devicecontrol.h"
#endif
//#include <lcd_nl6448.h>


#pragma section("video_buf1", NO_INIT)  
u8 	YUVBuf422		[800 * 608 *2 *4];
#pragma section("video_buf1", NO_INIT)  
u8 	YUVBuf420			[800 * 608 *2 *4];
  

u8 *pYUVBufs[4] = {NULL} ;

FILE *jpeg_filein;

u8	*pDestDescStartAddr;
u8	*pSrcDescStartAddr;

u8	*pYBuf, *pUBuf, *pVBuf, *pPing;






unsigned int 	JPEGFrameFormat;	// Frame format of decoded JPEG/MJPEG file

section ("mpp_nocache")
extern u8 PingFrame[LCD_WIDTH * LCD_DATA_PER_PIXEL * LCD_HEIGHT];

// local function prototype
int JPEG_Decode(char *filename);

void post_process_video(	u8 *ptr_src_yuv, 
							u8 *ptr_dest_yuv422,
							u8 *ptr_dest_rgb, 
							int decoded_image_width, 
							int decoded_image_height,
							int actual_image_width,
							int actual_image_height);
							
/*********************************************************************

    Function:       JPEG_decode

    Description:    Decodes a JPEG image (by interacting with JPEG Decode library)


*********************************************************************/	
int JPEG_decode(char* input_file_name)
{
	tJpegParam   				lParam;
    tJpegDecoder    			*JpegDecHandle = 0;
    FILE            			*inPtr = NULL;
	tIMG_BufferInfo 			lInputBufferInfo;
    MemObjHandle    			*StreamBuffer_Obj;
	uint8	        			*lOutputBuffer;
	// Parameters returned from CONFIG
    unsigned int    			JPEGWidth = 0;
    unsigned int    			JPEGHeight = 0;

	int32 				    	lResult = 0;
	int i;
	pYUVBufs[0]= &YUVBuf420[0];
	
	pDestDescStartAddr = YUVBuf422;
	pSrcDescStartAddr = YUVBuf420;
	
	
#ifdef ADI_MMSK_EXTRA_INFO		// macto to enable extra debug information
	// cycle counting
	static cycle_t              start_count;
	static cycle_t              final_count;
#endif

	// Start a new image
	if (JPEG_Param_INIT (&lParam) != E_SUCCESS)
	{
		return CODEC_ALGORITHM_ERROR;
	}

	// Configure the input buffer (get size from input file)
	inPtr = fopen(input_file_name, "rb");
	if(inPtr == NULL)
	{
		return CODEC_FILE_ERROR;;
	}
	
	// Get the size of JPEG file to be decoded
	fseek(inPtr, 0, SEEK_END);
	lInputBufferInfo.Length  = ftell (inPtr);			// size of input file
	
	// Dynamically allocate memory to copy the JPEG file for decoding
    StreamBuffer_Obj = JPEG_MemAlloc_NEW(lInputBufferInfo.Length,sizeof (uint8),MEM_TYPE_DATA);
	if(StreamBuffer_Obj == NULL)
	{
	    fclose(inPtr);
		return CODEC_MEMORY_ALLOCATION_ERROR;
	}
	// Get the address of dynamically allocated buffer
	lInputBufferInfo.Pointer = (uint8*)JPEG_MemAlloc_ADDRESS(StreamBuffer_Obj);

	// Read the input file
	fseek(inPtr, 0, SEEK_SET);

	// Copy the JPEG file to dynamically allocated memory for decoding
	if (fread(lInputBufferInfo.Pointer, sizeof (uint8), lInputBufferInfo.Length, inPtr) != lInputBufferInfo.Length)
	{
		//fprintf(fperr, "Could not read input image\n");
	    fclose(inPtr);
		JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
		return CODEC_FILE_ERROR;
	}

#ifdef ADI_MMSK_EXTRA_INFO		// macto to enable extra debug information
	printf("Input buffer size    = %d bytes\n", lInputBufferInfo.Length);
	printf("Input buffer address = 0x%x\n\n", lInputBufferInfo.Pointer);
#endif

	// Done with input file: close it
	fclose(inPtr);

	// Configure JPEG library to decode the copied JPEG image
	lResult = JPEG_Param_CONFIG(&lParam, JPEG_POINTER_INPUT, (int)&lInputBufferInfo);
	if(lResult != E_SUCCESS)	JPEG_ProcessErrorCode(lResult, "JPEG_Param_CONFIG");
    
    // Create a new JPEG Decoder instance   	
	JpegDecHandle = JPEG_Decoder_NEW(&lParam);
	if (JpegDecHandle == NULL)
	{
	    //fprintf(fperr, "Could not create JPEG decoder instance\n");
		JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
		return CODEC_ALGORITHM_ERROR;
	}

	// Process the JPEG header and extract image parameters
	lResult = JPEG_ProcessHeader(JpegDecHandle, &lParam);
	if (lResult != E_SUCCESS)
	{
		JPEG_ProcessErrorCode(lResult, "JPEG_ProcessHeader");
		JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
		JPEG_Decoder_DELETE(JpegDecHandle);
		return CODEC_FILE_ERROR;
	}
	
	
	// Get the JPEG image width
	lResult = JPEG_Param_STATUS(&lParam, JPEG_FRAME_WIDTH, &JPEGWidth);
	if(lResult != E_SUCCESS)	
		JPEG_ProcessErrorCode(lResult, "JPEG_Param_STATUS");
    // Get the JPEG image 272
    lResult = JPEG_Param_STATUS(&lParam, JPEG_FRAME_HEIGHT, &JPEGHeight);
	if(lResult != E_SUCCESS)	
		JPEG_ProcessErrorCode(lResult, "JPEG_Param_STATUS");
    // Get the JPEG image frame format (YUV4xx/RGG)
	lResult = JPEG_Param_STATUS(&lParam, JPEG_IMAGEFORMAT, &JPEGFrameFormat);
	if(lResult != E_SUCCESS)	
		JPEG_ProcessErrorCode(lResult, "JPEG_Param_STATUS");

    // Check the decoded JPEG image Frame Format
	if (JPEGFrameFormat != 1)
	{
		JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
		JPEG_Decoder_DELETE(JpegDecHandle);
		return CODEC_SUCCESS;
	}
	
	// Pointer to (JPEG decoded) output buffer
	lOutputBuffer = (uint8*)pYUVBufs[0];
		    
	// Give the output buffer pointer to JPEG Decoder library
	lResult = JPEG_Param_CONFIG(&lParam, JPEG_POINTER_OUTPUT, (int)lOutputBuffer);
	if(lResult != E_SUCCESS)	JPEG_ProcessErrorCode(lResult, "JPEG_Param_CONFIG");

	// Decode the JPEG image
	lResult = JPEG_DecodeImage(JpegDecHandle, &lParam);

	if (lResult != E_SUCCESS)
	{
	    JPEG_ProcessErrorCode(lResult, "JPEG_DecodeImage");
		JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
		JPEG_Decoder_DELETE(JpegDecHandle);
		return CODEC_ALGORITHM_ERROR;
	}
	
	// Clean up
	JPEG_Decoder_DELETE(JpegDecHandle);
	JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
	
	/* YUV to RGB Conversion */
	post_process_video(	YUVBuf420, YUVBuf422, PingFrame, JPEGWidth, JPEGHeight, lParam.actualWidth, lParam.actualHeight);
	

	
  	return CODEC_SUCCESS;
}









/*****/

