// Filename : mjpeg.h
//
// This file was initially generated by SpaceStudio but is meant to be modified
// by the user.
#ifndef MJPEG_H
#define MJPEG_H

#include "spacecomp.h"
#include "abstract_module.h"
#include "application_definitions.h"

#include "jpeg.h"
#include "vld_data.h"
#include "iqzz_data.h"
#include "idct_data.h"
#include "libu_data.h"
#include "throughput_monitor.h"

// Do NOT move macros, functions and includes beginning with "spacecomp".

class mjpeg: public abstract_module {
	SPACECOMP_START(mjpeg, INDEX, mjpeg);

public:
	mjpeg(SPACECOMP_CTOR_PARAMS(mjpeg, INDEX));

	void thread(SPACECOMP_THREAD_PARAMS(mjpeg, INDEX, thread));

#if SPACE_SIMULATION
	unsigned long long get_timer_value();
#endif

private:
	unsigned int m_nbFrames;
	unsigned int m_uiOffset;
	SPACE_ALIGNED unsigned char m_Buffer[4];
	bool m_BufferValid;

	unsigned int m_nbHuff;
	unsigned int m_nbQuant;

	unsigned int m_height, m_width, m_nb_comp ;
	unsigned int m_HiVi[NB_MAX_COMP];

	unsigned int m_BLOCKS_H, m_BLOCKS_W;
#if defined(SPACE_SIMULATION) || defined(SPACE_ARCHITECTURE_IMPLEMENTATION) && SPACE_OS == SPACE_OS_LINUX
	throughput_monitor m_throughput;
#endif
    unsigned long m_frames_processed = 0;
    double m_total_caculation_delta = 0.0;

	vld_struct m_vld_data;
	iqzz_struct m_iqzz_data;
	idct_struct m_idct_data;
	libu_struct m_libu_data;

	///
	/// Methods
	///
	void init_values();
	unsigned short get_next_mk();
	void skip_segment();
	void find_info(void);
	unsigned char read_8_bits();
	unsigned short read_16_bits();
	void skip_bytes(unsigned short NbBytes);

	//VLD
	void header_VLD();
	void loadTable_VLD(void);
	void bitreader_init(bitreader_context *cont);
	void check_ff(unsigned char value);
	void huff_tables_init( huff_context *cont );
	int huff_load_tables( huff_context *cont);
	int intceil(int N, int D);
	void data_pipeline();
	unsigned short read_data_VLD();
	void vld_decode_unpack_block( bitreader_context *bits, char mustOutput, huff_context *huff, cd_t *comp);
	int huff_get_symbol( bitreader_context *cont, huff_context *huff, int select );
	unsigned char bitreader_get_one(bitreader_context *cont);
	unsigned int bitreader_get(bitreader_context *cont, int number);
	long reformat(unsigned int S, int good);

	//IQZZ
	void loadTable_IQZZ(void);
	void load_multi_quant_table(unsigned char QuantizationTables[MAX_Q_TABLE][Q_TABLE_SIZE], int nbQuant);
	void update_values_IQZZ(unsigned int comp_cnt);
	void operation_IQZZ(short dataInput[]);

	//IDCT
	void operation_IDCT(short dataInput[]);
	void rot(int f, int k, int x, int z, int* rx, int* ry);
	void idct_1d(int* Y);

	//LIBU
	void operation_LIBU_readY(unsigned char dataInput[]);
	void operation_LIBU_readCb(unsigned char dataInput[]);
	void operation_LIBU_readCr(unsigned char dataInput[]);
	void init_LIBU();
	void endOfImage(unsigned int currentFrame);
	void calculate_output_pixel(bool grayScale);
	void operation_LIBU_pixel(unsigned char dataInput[]);
	void operation_LIBU(unsigned char dataInput[]);
	unsigned int ycbcr2rgba(unsigned char y, unsigned char cb, unsigned char cr);
	unsigned int grayscale2rgba(unsigned char y);

	void reset_timer();
	void print_timer_value();
	void end_application();

	SPACECOMP_END(mjpeg, INDEX, mjpeg);
};

#endif
