//	==========================================================================
//	Utils.c
//	(c) 2020, Aurel Dumitru
//
//	Description:
//  MainLoop operations
//	==========================================================================

// Includes
#include <control.h>
#include <string.h>
#include "main.h"
#include "jpeg_utils.h"
#include "utils.h"
#include "calibrations.h"

/* Defines */
#define JPG_MAX_CHUNK_SIZE_IN   ((uint32_t)(960 * 3 * 8))
#define JPG_MAX_CHUNK_SIZE_OUT  ((uint32_t)(4096))

/* Data */
uint8_t* Jpg_ImageBuffer;
uint8_t  Jpg_McuDataInBuffer[JPG_MAX_CHUNK_SIZE_IN];
uint8_t* Jpg_DataOutBuffer;

JPEG_ConfTypeDef Jpg_Conf;
JPEG_RGBToYCbCr_Convert_Function pRGBToYCbCr_Convert_Function;
uint32_t Jpg_McuTotalNb;
uint8_t* Jpg_RgbImageIn;
uint32_t Jpg_RgbInputImageIndex;
uint32_t Jpg_RgbInputImageSize_Bytes;
uint32_t Jpg_DataBufferSize;
uint32_t Jpg_ChunkSizeIn;



/* Private operations */
uint8_t* Jpg_StartConversion(uint32_t SizeX, uint32_t SizeY, uint32_t* Size)
{
	uint32_t ImageArea = SizeX*SizeY;
	uint32_t ImageQuality;

	Jpg_ImageBuffer			= Utils_GetSparePsramPtr();
	Jpg_RgbImageIn			= Utils_GetDemosaicImgPtr();
	Jpg_RgbInputImageIndex	= 0;
	Jpg_ChunkSizeIn			= SizeX*3*8;
	Jpg_DataOutBuffer		= Jpg_ImageBuffer;

	if (ImageArea >= 80000)
		ImageQuality = 75;
	else
		if (ImageArea >= 40000)
			ImageQuality = 80;
		else
			if (ImageArea >= 10000)
				ImageQuality = 85;
			else
				ImageQuality = 90;

    // Fill Encoding Params
	Jpg_Conf.ImageWidth  = SizeX;
	Jpg_Conf.ImageHeight = SizeY + C_ActivateContourDraw*32;
	Jpg_Conf.ImageQuality = ImageQuality;
	Jpg_Conf.ChromaSubsampling = JPEG_444_SUBSAMPLING;
	Jpg_Conf.ColorSpace = JPEG_YCBCR_COLORSPACE;
    HAL_JPEG_ConfigEncoding(&hjpeg, &Jpg_Conf);

    // Get YCbCr encoding function
    JPEG_GetEncodeColorConvertFunc(&Jpg_Conf, &pRGBToYCbCr_Convert_Function, &Jpg_McuTotalNb);

	(void)pRGBToYCbCr_Convert_Function(Jpg_RgbImageIn + Jpg_RgbInputImageIndex, Jpg_McuDataInBuffer, 0, Jpg_ChunkSizeIn, &Jpg_DataBufferSize);
	Jpg_RgbInputImageIndex += Jpg_ChunkSizeIn;

	/* Start JPEG encoding */
	HAL_JPEG_Encode(&hjpeg, Jpg_McuDataInBuffer, Jpg_DataBufferSize, Jpg_DataOutBuffer, JPG_MAX_CHUNK_SIZE_OUT, 5000);
	*Size = (uint32_t)(Jpg_DataOutBuffer - Jpg_ImageBuffer);
	return Jpg_ImageBuffer;
}


/**
  * @brief  JPEG Get Data callback
  * @param hjpeg: JPEG handle pointer
  * @param NbDecodedData: Number of decoded (consummed) bytes from input buffer
  * @retval None
  */
void HAL_JPEG_GetDataCallback(JPEG_HandleTypeDef *hjpeg, uint32_t NbDecodedData)
{
	if (NbDecodedData != Jpg_DataBufferSize)
		HAL_JPEG_ConfigInputBuffer(hjpeg, Jpg_McuDataInBuffer + NbDecodedData, Jpg_DataBufferSize - NbDecodedData);
	else
	{
		(void)pRGBToYCbCr_Convert_Function(Jpg_RgbImageIn + Jpg_RgbInputImageIndex, Jpg_McuDataInBuffer, 0, Jpg_ChunkSizeIn, &Jpg_DataBufferSize);
		Jpg_RgbInputImageIndex += Jpg_ChunkSizeIn;
		HAL_JPEG_ConfigInputBuffer(hjpeg, Jpg_McuDataInBuffer, Jpg_DataBufferSize);
	}
}


/**
  * @brief  JPEG Data Ready callback
  * @param hjpeg: JPEG handle pointer
  * @param pDataOut: pointer to the output data buffer
  * @param OutDataLength: length of output buffer in bytes
  * @retval None
  */
void HAL_JPEG_DataReadyCallback (JPEG_HandleTypeDef *hjpeg, uint8_t *pDataOut, uint32_t OutDataLength)
{
	/* Update JPEG encoder output buffer address*/
	Jpg_DataOutBuffer += OutDataLength;
	HAL_JPEG_ConfigOutputBuffer(hjpeg, Jpg_DataOutBuffer, JPG_MAX_CHUNK_SIZE_OUT);
}

/**
  * @brief  JPEG Error callback
  * @param hjpeg: JPEG handle pointer
  * @retval None
  */
void HAL_JPEG_ErrorCallback(JPEG_HandleTypeDef *hjpeg)
{
  Error_Handler();
}
