/* YUNTAI KYONG
Advanced Internet Service
term project
*/
#ifndef _ELEMENTARY_STREAM_H_
#define _ELEMENTARY_STREAM_H_

#include <winsock2.h>

#include "fileStream.h"
#include "socket.h"

/* MPEG start and end codes */
#define START_CODE_PREFIX		0x000001
#define EXTENSION_START_CODE	0x000001b5
#define GROUP_START_CODE		0x000001b8
#define SEQUENCE_HEADER_CODE	0x000001b3
//#define SEQUENCE_END_CODE		0x00000001b7
#define SEQUENCE_END_CODE		0x000001b7
#define USER_DATA_START_CODE	0x000001b2
#define PICTURE_START_CODE		0x00000100
#define SLICE_START_CODE_BEGIN	0x00000101
#define SLICE_START_CODE_END	0x000001AF
#define TRUE 1
#define FALSE 0

/* Picture type codes */
#define I_FRAME 1
#define P_FRAME 2
#define B_FRAME 3
#define D_FRAME 4

#define MAX_BLOCKS 1024
#define INITIAL_DATA 10240

typedef struct _VIDEO_SPECIFIC_HEADER
{
	/* byte 0,1 */
	unsigned int TR:10;			/* Temporal+Reference */
	unsigned int T:1;			/* Specific Header Extension */
	unsigned int MBZ:5;			/* unused, Must be set zero */
	   
    
	/* byte 2,3 */
	unsigned int FFC:3;			/* forward_f_code			*/
	unsigned int FFV:1;			/* full_pel_forward_vector	*/
	unsigned int BFC:3;			/* backward_f_code			*/
	unsigned int FBV:1;			/* full_pel_backward_vector */
			
    unsigned int P:3;			/* Picture-Type				*/
	unsigned int E:1;			/* End-of-Slice				*/
	unsigned int B:1;			/* Beginning of slice		*/
	unsigned int S:1;			/* Sequence_header_present  */
	unsigned int N:1;			/* New Picture Header		*/
	unsigned int AN:1;			/* Active N Bit				*/
	  
    
	
} VIDEO_SPECIFIC_HEADER;


typedef struct _MPEG2_VIDEO_SPECIFIC_HEADER_EXTENSION
{
	/* byte 0,1 */
	unsigned int backward_vertical_f_code:4;		/* f_[1,1]	*/
	unsigned int backward_horizontal_f_code:4;		/* f_[1,0]	*/
	unsigned int forward_vertical_f_code:4;			/* f_[0,1]	*/
	unsigned int forward_horizontal_f_code:4;		/* f_[0,0]	*/	
	unsigned int E:1;								/* Extensions present */
	unsigned int X:1;								/* Unused	*/
	
	
	/* byte 2,3 */
	unsigned int D:1;								/* composite_display_flag   */
	unsigned int G:1;								/* progressive frame   */
	unsigned int H:1;								/* chroma_420_type   */
	unsigned int R:1;								/* repeat_first_field   */
	unsigned int A:1;								/* alternate scan   */
	unsigned int V:1;								/* intra_vlc_format   */
	unsigned int Q:1;								/* q_scale type   */
	unsigned int C:1;								/* concealment_motion_vectors   */
	unsigned int P:1;								/* frame_predicted_frame_dct   */
	unsigned int T:1;								/* top_field_first  */
	unsigned int PS:2;								/* picture_structure  */
	unsigned int DC:2;								/* Intra_DC_precision  */

} MPEG2_VIDEO_SPECIFIC_HEADER_EXTENSION;


/* structures for holding 'sequence_header' information */
typedef struct
{
	unsigned int horizontal_size_value;			//	12
	unsigned int vertical_size_value;			//  12
	unsigned int aspect_ratio_infomation;		//	4
	unsigned int frame_rate_value;				//	4
	unsigned int bit_rate_value;				//	18
	unsigned int marker_bit;					//	1
	unsigned int vbv_buffer_size_value;			//  10
	unsigned int constrained_parameters_flag;	//  1
	
	unsigned int load_intra_quantiser_matrix;	//  1
	unsigned char intra_quantiser_matrix[64];	
	
	unsigned int load_non_intra_quantiser_matrix;	// 1
	unsigned char non_intra_quantiser_matrix[64];
	
	unsigned int ext_data_size, user_data_size, sequence_header_size;
	unsigned char ext_data[1024], user_data[1024];
} sequence_header;

typedef struct
{
	unsigned int temporal_reference;			// 10
	unsigned int picture_config_type;			// 3
	unsigned int vbv_delay;						// 16
	unsigned int full_pel_forward_vector;		// 1
	unsigned int forward_f_code;				// 3
	unsigned int full_pel_backward_vector;		// 1
	unsigned int backward_f_code;				// 3
	unsigned int extra_bit_picture;				// 1
	unsigned int extra_information_picture;		// 8
	unsigned int picture_header_size;
} picture_header;

typedef struct
{
	unsigned int extension_ID;				// 4
	unsigned int f_code00;					// 4
	unsigned int f_code01;					// 4
	unsigned int f_code10;					// 4
	unsigned int f_code11;					// 4
	unsigned int intra_dc_precision;		// 2
	unsigned int picture_structure;			// 2
	unsigned int top_field_first;			// 1
	unsigned int frame_pred_and_frame_dct;	// 1
	unsigned int cpmcealment_motion_vectors;// 1
	unsigned int q_scale_type;				// 1
	unsigned int intra_vic_format;			// 1
	unsigned int alternate_scan;			// 1
	unsigned int repeat_first_field;		// 1	
	unsigned int chroma_420_type;			// 1
	unsigned int progressive_frame;			// 1
	unsigned int composite_display_flag;	// 1
	
	unsigned int v_axis;					// 1	
	unsigned int field_sequence;			// 3
	unsigned int sub_carrier;				// 1
	unsigned int burst_amplitude;			// 7
	unsigned int sub_carrier_phase;			// 8

} extension_header;

typedef struct
{
	unsigned int time_code;
	unsigned int closed_gop;
	unsigned int broken_link;	
	
	unsigned int gop_ext_data_size;
	unsigned char gop_ext_data[1024];
	
	unsigned int gop_user_data_size;
	unsigned char gop_user_data[1024];

	unsigned int gop_size;
} gop_header;

#define CLOSED_GOP 1
#define BROKEN_LINK 2
#define MAX_PICTURES 128
/* class definition */
#define RTP_VERSION 2
#define MPV_PAYLOAD 32

typedef unsigned char u_char;

typedef struct _RTP_HEADER
{
	/* byte 0 */
	u_char csrc_len:4;		/* expect 0 */
	u_char extension:1;		/* expect 1, see RTP_OP below */
	u_char padding:1;		/* expect 0 */
	u_char version:2;		/* expect 2 */
	/* byte 1 */
	u_char payload:7;		/* RTP_PAYLOAD_RTSP */
	u_char marker:1;		/* expect 1 */
	/* bytes 2, 3 */
	unsigned short seq_no;			
	/* bytes 4-7 */
	unsigned  long timestamp;		
	/* bytes 8-11 */
    unsigned long ssrc;			/* stream number is used here. */
} RTP_HEADER;

typedef struct _RTP_PACKET
{
  RTP_HEADER *RTP_header;
  unsigned char *payload;         /* payload portion of RTP packet */
} RTP_PACKET;

class elementaryStream
{
	
public:
	elementaryStream(fileStream *fs, CSocket *sock,unsigned long,unsigned short);
		
	int next_start_code(void);
	int find_next_start_code(void);
	

	int get_one_slice(unsigned char *payload, int bytesToGo);
	
	int get_sequence_header(unsigned char *payload, int bytesToGo);
	int get_picture_header(unsigned char *payload, int bytesToGo);
	int get_gop_header( unsigned char *payload, int bytesToGo);
	int get_extension(unsigned char *payload, int bytesToGo);	
	int get_user_data(unsigned char *payload, int bytesToGo);
	int get_slices(unsigned char *payload, int bytesToGo);

	void print_sequence_header(void);
	void print_gop(void);
	//void print_picture(int temporal_reference);
	void print_picture_header();


	void getVideoSpecficeHeader( unsigned char*,int,int,int,int,int);
	void getMPEG2ExtensionHeader( unsigned char* );
	int sendRTPpacket(unsigned char*,int,int,int);
					
private:
	fileStream *fs;
	CSocket *sock;
	unsigned short m_seq_num;
	unsigned long m_time_stamp;
	unsigned long m_stream_num;
	unsigned int m_slice_start_code;
	sequence_header sequence_h;
	gop_header		gop_i;
	picture_header	picture_h;
	extension_header extension_h;
	
public:
	int m_pic_type;
	int hold;
};
#endif /* _ELEMENTARY_STREAM_H_ */
