#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vsparser.h"

u32 h264_parse(u32 buffer_start_addr, u32 buffer_size, u8 *src_mem, u32 *frame_start_addr,  u32 *frame_size, u8 is_first_seq_header)
{
	u32 i ;
	u32 num_start_code ;
	u32 hd_start_code ;
	int rbsp_base;

	u8  tmp_0, tmp_1 ;
	u8 *tmp_mem ;

	i              = 0 ;
	num_start_code = 0 ;
	hd_start_code  = 0 ;

	while(1)
	{
		tmp_mem = src_mem + i ;

		if (((*(tmp_mem)==0x00) && (*(tmp_mem+1)==0x00) && (*(tmp_mem+2)==0x00) && (*(tmp_mem+3)==0x01)) ||
			((*(tmp_mem)==0x00) && (*(tmp_mem+1)==0x00) && (*(tmp_mem+2)==0x01)))

		{
			rbsp_base = buffer_start_addr + i;
			
			if((*(tmp_mem)==0x00) && (*(tmp_mem+1)==0x00) && (*(tmp_mem+2)==0x00) && (*(tmp_mem+3)==0x01))
			{
				i++;
				tmp_mem = src_mem + i;
			}

			tmp_0 = *(tmp_mem+3) & 0x1f ;     //=== nal_unit_type

			if (tmp_0==0x06 || tmp_0==0x07 || tmp_0==0x08)  //=== SPS, PPS, SEI
			{
				hd_start_code++ ;
				if (num_start_code==0 && hd_start_code==1) 
					*frame_start_addr = rbsp_base;
				if (num_start_code==1) num_start_code++ ;
			}

#ifdef _SLICE_BASED_INTERFACE_
			if (is_first_seq_header && tmp_0==0x06)  //=== SEI
			{
				*frame_size     = rbsp_base - *frame_start_addr ;
				num_start_code = 2 ;
				break ;
			}
#endif

			if (tmp_0==0x01 || tmp_0==0x05)    //=== non-IDR picture, IDR picture
			{
				if (is_first_seq_header)
				{
					*frame_size     = rbsp_base - *frame_start_addr ;
					num_start_code = 2 ;
					break ;
				}
/// sungho.roh
#ifdef _SLICE_BASED_INTERFACE_
				num_start_code++;
				if (num_start_code==1 && hd_start_code==0) *frame_start_addr = rbsp_base;
#else
				tmp_1 = *(tmp_mem+4) & 0x80 ;  //=== first_mb_in_slice is only 1'b1
				if (tmp_1==0x80)
				{
					num_start_code++ ;
					if (num_start_code==1 && hd_start_code==0) *frame_start_addr = rbsp_base;
				}
#endif
			}

			if (num_start_code==2)
			{
				*frame_size = rbsp_base - *frame_start_addr;
				break ;
			}

			i+=3;
		}
		else
		{
			i++ ;
		}
		if (i>=buffer_size) break ;
	}

	if (num_start_code==2) return(0) ;    //=== 2개의 start code
	if (num_start_code==1) return(1) ;    //=== 1개의 start code
	else                   return(2) ;    //=== 0개의 start code
}

//static volatile u8 MPEG1_FLAG=1;
u8 MPEG1_FLAG=1;
u32 mpeg2_parse(u32 buffer_start_addr, u32 buffer_size, u8 *src_mem, u32 *frame_start_addr,  u32 *frame_size, u8 is_first_seq_header)
{
	u32 i = 0;
	u32 num_start_code = 0;
	u32 hd_start_code  = 0;	
	u32 frame_enable = 0;
	u32 bit_len ;
	u32 byte_len ;
	u32 rem_len ;

	u8 pic_coding_type ;
	u8 pic_structure ;   //=== 0-Reserved, 1-Top field, 2-Bottom field, 3-Frame
	u8 tmp_0 ;
	u8 tmp_1 ;
	u8 *tmp_mem ;

	while(1)
	{
		tmp_mem = src_mem + i ;
		if(i + 3 > buffer_size - 1)
		{
			break;
		}
		
		if ((*(tmp_mem)==0x00) && (*(tmp_mem+1)==0x00) && (*(tmp_mem+2)==0x01))
		{
			tmp_0 = *(tmp_mem+3) ;
			if (tmp_0==0xb3 || tmp_0==0xb8)
			{
				hd_start_code++ ;
				if (num_start_code==0 && hd_start_code==1)
				{
					*frame_start_addr = buffer_start_addr + i;
				}
				if (num_start_code==1)
				{
					num_start_code++;
				}
			}
	
			if (tmp_0==0x00)
			{
				if(is_first_seq_header)
				{
					*frame_size = buffer_start_addr + i - *frame_start_addr ;
					num_start_code = 2;					
					break;
				}
				
				num_start_code++ ;
				if (num_start_code==1 && hd_start_code==0) 
					*frame_start_addr = buffer_start_addr + i ;
				
			}

			if (num_start_code==2)
			{
				*frame_size = buffer_start_addr + i - *frame_start_addr ;
				break ;
			}
		}
		
		i++ ;
		if (i>buffer_size) break ;
	}

	if (num_start_code==2) return(0) ;    //=== 2개의 start code
	if (num_start_code==1) return(1) ;    //=== 1개의 start code
	else                   return(2) ;    //=== 0개의 start code
}


u32 mpeg4_parse(SSBSIP_MFC_CODEC_TYPE standard, u32  buffer_start_addr, u32  buffer_size, u8 *src_mem,
						      u32 *frame_start_addr,  u32 *frame_size, u8 is_first_seq_header)
{
	u32 i ;
	u32 num_start_code ;
	u32 hd_start_code ;

	u8  tmp_0, tmp_1 ;
	u8 *tmp_mem ;
	u8 short_header = false;

	i              = 0 ;
	num_start_code = 0 ;
	hd_start_code  = 0 ;

	while(i<buffer_size)
	{
		tmp_mem = src_mem + i ;

		if ((*(tmp_mem)==0x00) && (*(tmp_mem+1)==0x00) && (*(tmp_mem+2)==0x01))
		{
			break;
		}

		if ((*(tmp_mem)==0x00) && (*(tmp_mem+1)==0x00))
		{
			/* Hypo : There's no kind of 0x000001xx in the short header video. 20090723 */
#ifndef _SLICE_BASED_INTERFACE_
			short_header = true;
#endif
			break;
		}
		i++;
	}
	
	i = 0;
	while(1)
	{
		tmp_mem = src_mem + i ;

		if ((*(tmp_mem)==0x00) && (*(tmp_mem+1)==0x00) && (*(tmp_mem+2)==0x01))
		{
			break;
		}

		if ((*(tmp_mem)==0x00) && (*(tmp_mem+1)==0x00))
		{
			/* Hypo : There's no kind of 0x000001xx in the short header video. 20090723 */
#ifndef _SLICE_BASED_INTERFACE_
			short_header = true;
#endif
			break;
		}
		i++;
	}
	
	i = 0;
	while(1)
	{
		tmp_mem = src_mem + i ;
		if (short_header == false)
		{
			if ((*(tmp_mem)==0x00) && (*(tmp_mem+1)==0x00) && (*(tmp_mem+2)==0x01))
			{
				tmp_0 = *(tmp_mem+3) ;
				tmp_1 = (tmp_0 & 0xf0) ;

				if (tmp_0==0xb0 || tmp_0==0xb5 || tmp_0==0xb2 || tmp_0==0xb3 || tmp_1==0x00 || tmp_1==0x10 || tmp_1==0x20)
				{
					hd_start_code++ ;
					if (num_start_code==0 && hd_start_code==1) *frame_start_addr = buffer_start_addr + i ;
					if (num_start_code==1) num_start_code++ ;
				}

				if (tmp_0==0xb6)
				{
					if(is_first_seq_header) /* The first seq_hd would be processed individually. 20090626 */
					{
						*frame_size = buffer_start_addr + i - *frame_start_addr;
						num_start_code = 2;
						break;
					}
					num_start_code++ ;
					if (num_start_code==1 && hd_start_code==0) *frame_start_addr = buffer_start_addr + i ;
				}

				if (num_start_code==2)
				{
					*frame_size = buffer_start_addr + i - *frame_start_addr ;
					break ;
				}
			}
			
#ifdef _SLICE_BASED_INTERFACE_
			/* To support the slice decoding, the resync marker would be used as a ruler. 20090723 */
			else if ((*(tmp_mem)==0x00) && (*(tmp_mem+1)==0x00))
			{
				tmp_0 = (*(tmp_mem+2) >> 7) & 0x1;

				if(tmp_0 == 0x1)
				{
					num_start_code++ ;
					if (num_start_code==1) *frame_start_addr = buffer_start_addr + i ;
					if (num_start_code==2)
					{
						*frame_size = buffer_start_addr + i - *frame_start_addr ;
						break ;
					}
				}
			}
#endif
			else
			{
				/* Undefined pattern might be found!! */
			}
		}
		else
		{
			/*
			if(i >=  buffer_size)
			{
				break;
			}
			*/
			
			if ((*(tmp_mem)==0x00) && (*(tmp_mem+1)==0x00))
			{
				tmp_0 = (*(tmp_mem+2) >> 2) & 0xff ;

				if (tmp_0==0x20)
				{
					num_start_code++ ;
					if (num_start_code==1) *frame_start_addr = buffer_start_addr + i ;
					if (num_start_code==2)
					{
						*frame_size = buffer_start_addr + i - *frame_start_addr ;
						break ;
					}
				}
			}
		}

		i++ ;
		if (i + 2 >= buffer_size) break ;
	}

	if (num_start_code==2) return(0) ;    //=== 2개의 start code
	if (num_start_code==1) return(1) ;    //=== 1개의 start code
	else                   return(2) ;    //=== 0개의 start code
}


u32 vc1_parse(u32 buffer_start_addr, u32 buffer_size, u8 *src_mem,
				u32 *frame_start_addr,  u32 *frame_size, u8 rcvFlag, u8 is_first_seq_header)
{
	u32 ret;
	
	if(rcvFlag)
	{		
		ret = rcv_parse(buffer_start_addr, buffer_size, src_mem, frame_start_addr, frame_size);
	}
	else
	{
		ret = vc1_parse_advancedProfile_Frame(buffer_start_addr, buffer_size,
										src_mem, frame_start_addr, frame_size, is_first_seq_header);
	}
	
	return ret;
}


u32 rcv_parse(u32 buffer_start_addr, u32 buffer_size, u8 *src_mem,
			u32 *frame_start_addr,  u32 *frame_size)
{
	static int frame_count = 0;
	u32 index = 0;

	if(src_mem[index+3] == 0xC5)
	{
		// sequence header
		//u_int numframes = (src_mem[index+2] << 16) | (src_mem[index+1] << 8) | src_mem[index];
		index += 4;		// plus 0xC5 + NUM_FRAMES
		index += 4; 	// plus 0x00000004;
		index += 4;		// plus STRUCT_C
		index += 8;		// plus STRUCT_A
		index += 4;		// plus 0x0000000C;
		index += 12;	// plus STRUCT_B
		#if 0
		*frame_start_addr = buffer_start_addr+8;
		*frame_size = index-8;
		#else	// for MFC fw 11/30
		*frame_start_addr = buffer_start_addr;
		*frame_size = index;
		#endif		
	}
	else
	{
		u32 framesize = (src_mem[index+2] << 16) | (src_mem[index+1] << 8) | src_mem[index];
		index += 4;		// plus KEY + RES + FRAMESIZE
		index += 4;		// plus timestamp
		index += framesize;
		#if 0
		*frame_start_addr = buffer_start_addr+4;
		*frame_size = index-4;
		#else	// for MFC fw 11/30
		*frame_start_addr = buffer_start_addr;
		*frame_size = index;
		#endif		
	}


	if(index >= buffer_size)
		return 1;
	return 0;
}

static u8 isInterlace = false;

u8 SkippedPictureCheck(u8 *src_mem, u32 index)
{
	u32 ptype = 0;
	
	if(isInterlace)
	{
		// parsing ptype after FCM
		if(src_mem[index] & 0x80)
		{
			// FCM is 2-bit
			ptype = src_mem[index] & 0x3c;
			ptype >>= 2;
		}
		else
		{
			// FCM is 1-bit
			ptype = src_mem[index] & 0x78;
			ptype >>= 3;
		}
	}
	else
	{
		// parsing ptype
		ptype = src_mem[index] & 0xf0;
		ptype >>= 4;
	}

	return ptype == 0xf ? 1 : 0;
}

u32  vc1_parse_advancedProfile_Frame(
							   u32  buffer_start_addr, u32   buffer_size,
							   u8 *src_mem,
							   u32 *frame_start_addr,  u32 *frame_size, u8 is_first_seq_header)
{
	u32 Size = 0;
	u32 index = 0;
	u32 firstByte, secondByte, thirdByte;
	u32 previousSuffixByte = 0;
	u32 currentSuffixByte;
	u8  seqHeaderFlag = false;
	u8  entryHeaderFlag = false;
	u8  frameEndFlag = false;

	while(1)
	{
		if((index + 3) > buffer_size) return 1; // last frame OR error

		// Sequence 		start_code 0x0000010F
		// Entry			start_code 0x0000010E
		// Frame			start_code 0x0000010D
		// Field			start_code 0x0000010C
		// Slice			start_code 0x0000010B
		// End-Of-Sequence	start_code 0x0000010A

		firstByte = src_mem[index];
		secondByte = src_mem[index+1];
		thirdByte = src_mem[index+2];

		if(firstByte == 00 && secondByte == 00 && thirdByte == 01)
		{ // start_code ?
			if(is_first_seq_header)
			{
				if(entryHeaderFlag) break;
			
				currentSuffixByte = src_mem[index+3];
			
				if(currentSuffixByte == 0x0F)
				{
					*frame_start_addr = buffer_start_addr + index;
					seqHeaderFlag = true;
				}
				else if(currentSuffixByte == 0x0E)
				{ // entry ?
					if(seqHeaderFlag)	entryHeaderFlag = true;
				}
			}
			else
			{
				currentSuffixByte = src_mem[index+3];

				if(currentSuffixByte == 0x0F || currentSuffixByte == 0x0E || currentSuffixByte == 0x0A)
				{ // sequence or entry ?
					if(   previousSuffixByte == 0x0B
					   || previousSuffixByte == 0x0C
					   || previousSuffixByte == 0x0D) break;

					if(currentSuffixByte == 0x0F) seqHeaderFlag = true;

					if(previousSuffixByte != 0x0F)
						*frame_start_addr = buffer_start_addr + index;

					if(seqHeaderFlag == true) previousSuffixByte = 0x0F;
					else					  previousSuffixByte = currentSuffixByte;
				}
				else if(   currentSuffixByte == 0x0C
						|| currentSuffixByte == 0x0D)
//				else if(currentSuffixByte == 0x0D)
				{ // frame ?
					if(previousSuffixByte != 0x0F && previousSuffixByte != 0x0E)
					{
						if(frameEndFlag == false)
							*frame_start_addr = buffer_start_addr + index;
						else
							break;
					}
					frameEndFlag = true;
					previousSuffixByte = currentSuffixByte;
				}
			}
		}
		index += 1;
	}

	*frame_size = index;
	
	if (currentSuffixByte != 0x0A)
		return 0;
	else
		return 2;
}

// return type
// 0: one frame size is successfully determined AND there are still more frames
// 1,2: the size of the last frame is successfully determined. 
// 3: error (invalid standard)

u32 VsParser(SSBSIP_MFC_CODEC_TYPE standard, u32 buffer_start_addr, u32 buffer_size, /*u8* src_mem,*/
	u32 *frame_start_addr, u32 *frame_size, u8 bIsRcvFlag, u8 is_first_seq_header)
{
	u32 ret_value;
	
	u8 *src_mem;
	
	src_mem = (u8 *)buffer_start_addr;
	
	switch(standard)
	{
		case MPEG4_DEC :
		case DIVX311_DEC :	
		case DIVX412_DEC :
		case DIVX502_DEC :	
		case DIVX503_DEC :
		case XVID_DEC:
		case H263_DEC :
			ret_value = mpeg4_parse(standard, buffer_start_addr, buffer_size, src_mem,
											  frame_start_addr,  frame_size, is_first_seq_header);
			if(ret_value==1||ret_value==2)	*frame_size=buffer_size;
			break ;
		case MPEG2_DEC :
			ret_value = mpeg2_parse(buffer_start_addr, buffer_size, src_mem,
									frame_start_addr,  frame_size, is_first_seq_header);
			if(ret_value==1||ret_value==2)	*frame_size=buffer_size;
			break ;
		case H264_DEC :
			ret_value = h264_parse(buffer_start_addr, buffer_size, src_mem,
								   frame_start_addr,  frame_size, is_first_seq_header);
			if(ret_value==1||ret_value==2)	*frame_size=buffer_size;
			break ;
		case VC1_DEC:
			ret_value =	vc1_parse_advancedProfile_Frame(buffer_start_addr, buffer_size,
							src_mem, frame_start_addr, frame_size, is_first_seq_header);
			if(ret_value==1||ret_value==2)	*frame_size=buffer_size;
			break ;
		case VC1RCV_DEC: //RCV
			ret_value  = rcv_parse(buffer_start_addr, buffer_size, src_mem,
									frame_start_addr, frame_size);
			if(ret_value==1||ret_value==2)	{				
				*frame_size = buffer_size;	// for MFC fw 11/30			
			}	
			break;
		default :
			ret_value = 3 ;
			break ;
	}
	return ret_value ;
}

u8 compare_fourcc(unsigned char* FourCC, char* candidate)
{
	if(FourCC[0] == candidate[0] &&
		FourCC[1] == candidate[1] &&
		FourCC[2] == candidate[2] &&
		FourCC[3] == candidate[3])
		return true;
	return false;
}

void Copy8(u32 sa, u32 da, u32 bytes)
{
	u32 i;
	for (i=0; i<bytes; i++)
		*(u8 *)(da+i) = *(u8 *)(sa+i);
}

unsigned int read_word_little(RFILE* fp)
{
	unsigned char c[4];
	unsigned int value;
//	fread(c, 1, 4, fp);
//	memcpy(c, (void *)(fp->filestart + fp->offset), 4);
	Copy8((fp->filestart + fp->offset), (u32)c, 4);
	fp->offset += 4;
	value = (c[3]<<24) | (c[2] << 16) | (c[1] << 8) | c[0];	
	return value;
}

u8 get_fourcc(RFILE* fp, unsigned char* FourCC)
{
	int count;
	//if((count = fread(FourCC, 1, 4, fp)) < 4 || count == EOF)
	if(fp->filestart + fp->offset + 4 < fp->filesize)
	//if((count = fread(FourCC, 1, 5, fp)) < 5 || count == EOF)  //DS
		return false;
	//memcpy(FourCC, (void *)(fp->filestart + fp->offset), 4);
	Copy8((fp->filestart + fp->offset), (u32)FourCC, 4);
 	fp->offset += 4;
	return true;
}

u8 get_fourcc1(unsigned char* buf, unsigned char* FourCC)
{
	FourCC[0] = buf[0];
	FourCC[1] = buf[1];
	FourCC[2] = buf[2];
	FourCC[3] = buf[3];
	return true;
}


u8 _parse_avi_header(RFILE* fp, u32 start_position, u32 total_size, AVI_INFOs* info)
{	
	unsigned int position = 0;
	unsigned char c[4];

	while(position < total_size)
	{	
		unsigned int dwSize;
		unsigned char FourCC[5];
		u8 is_list = false;
		
		get_fourcc(fp, FourCC);
		position += 4;
		
		if(compare_fourcc(FourCC, "RIFF") || compare_fourcc(FourCC, "LIST"))
		{
			dwSize = read_word_little(fp) - 4;
			get_fourcc(fp, FourCC);		
			is_list = true;
			position += 8;
		}
		else if(compare_fourcc(FourCC, "avih"))
		{
			read_word_little(fp);	position += 4;	// dwSize
			read_word_little(fp);	position += 4;	// dwMicroSecPerFrame
			read_word_little(fp);	position += 4;	// dwMaxBytesPerSec
			read_word_little(fp);	position += 4;	// dwPaddingGranularity
			read_word_little(fp);	position += 4;	// dwFlags
			
			info->total_frames = read_word_little(fp);	position += 4;	// dwTotalFrames

			read_word_little(fp);	position += 4;	// dwInitialFrames
			read_word_little(fp);	position += 4;	// dwStreams
			read_word_little(fp);	position += 4;	// dwSuggestedBufferSize

			info->width = read_word_little(fp);	position += 4;	// dwWidth
			info->height = read_word_little(fp);	position += 4;	// dwHeight

			read_word_little(fp);	position += 4;	// dwReserved[0]
			read_word_little(fp);	position += 4;	// dwReserved[1]
			read_word_little(fp);	position += 4;	// dwReserved[2]
			read_word_little(fp);	position += 4;	// dwReserved[3]
			dwSize = 0;
			
		}
		//else if(compare_fourcc(FourCC, "strh"))
		//else if((compare_fourcc(FourCC, "strh")) || (compare_fourcc(FourCC, "strf"))) //DS
		else if(compare_fourcc(FourCC, "strf"))  //DS
		{
			dwSize = read_word_little(fp);
			
			//unsigned char fccType[5];
			//get_fourcc(fp, fccType);
			//fccType[4] = 0;
			//DS
			/*
			unsigned char fccType2[5];
			get_fourcc(fp, fccType2);
			fccType2[4] = 0;
			*/
			read_word_little(fp);
			read_word_little(fp);
			read_word_little(fp);
			//read_word_little(fp);
//			fread(c, 1, 3, fp);
			//memcpy(c, (void *)(fp->filestart + fp->offset), 3);
			Copy8((fp->filestart + fp->offset), (u32)c, 4);

			fp->offset += 4;
			
			//~DS
//			get_fourcc(fp, info->fccHandler);
//			info->fccHandler[4] = 0;

//			fread(info->fccHandler, 1, 5, fp);  //ys
			//memcpy(info->fccHandler, (void *)(fp->filestart + fp->offset), 5);
			Copy8((fp->filestart + fp->offset), (u32)info->fccHandler, 4);

			fp->offset += 4;
			
			info->fccHandler[4] = NULL;  //ys
			
			if(compare_fourcc(info->fccHandler, "MP4v") == true 		|| compare_fourcc(info->fccHandler, "mp4v") == true 
				|| compare_fourcc(info->fccHandler, "M4S2") == true		|| compare_fourcc(info->fccHandler, "DIV4") == true 
				|| compare_fourcc(info->fccHandler, "div4") == true 	|| compare_fourcc(info->fccHandler, "DIVX") == true
				|| compare_fourcc(info->fccHandler, "divx") == true	 	|| compare_fourcc(info->fccHandler, "MP42") == true
				|| compare_fourcc(info->fccHandler, "FMP4") == true)
				info->standard = MPEG4_DEC;
			else if(compare_fourcc(info->fccHandler, "DIV3") == true 	|| compare_fourcc(info->fccHandler, "div3") == true)
				info->standard = DIVX311_DEC;
			else if(compare_fourcc(info->fccHandler, "xvid") == true 	|| compare_fourcc(info->fccHandler, "XVID") == true)
				info->standard = XVID_DEC;
			else if(compare_fourcc(info->fccHandler, "MP2V") == true 	|| compare_fourcc(info->fccHandler, "mp2v") == true)
				info->standard = MPEG2_DEC;
			else if(compare_fourcc(info->fccHandler, "H263") 			|| compare_fourcc(info->fccHandler, "h263"))
				info->standard = H263_DEC;
			else if(compare_fourcc(info->fccHandler, "H264")	 		|| compare_fourcc(info->fccHandler, "h264"))
				info->standard = H264_DEC;
			else
			{
				return false;	
			}
			
			if(info->standard != 0xff)
			{
				return true;
			}
			
			dwSize -= 8;
			//position += 12;
			position += 24;  //DS
		}
		else if(FourCC[2] == 'd' || FourCC[2] == 'w')
		{
			dwSize = read_word_little(fp);
			position += 4;
			if(dwSize%2 == 1) 
			{
				dwSize++;
			}
		}
		else
		{
			dwSize = read_word_little(fp);			
			position += 4;
		}
		
		FourCC[4] = 0;
		
		if(is_list == true)
		{
			position += _parse_avi_header(fp, start_position + position, dwSize, info);
			if(info->standard != 0xff)
				return true;
		}
		else
		{			
//			fseek(fp, dwSize, SEEK_CUR);
			fp->offset += dwSize;
			position += dwSize;
		}
	}	
	return false;	
}

u8 parse_avi_header(RFILE* fp, int position, u32 total_size, SSBSIP_MFC_CODEC_TYPE* standard, u32* width, u32* height)
{
	AVI_INFOs info;
	u8 ret;
	info.standard = UNKNOWN_TYPE;

	ret = _parse_avi_header(fp, position, total_size, &info);
//	rewind(fp);
	fp->offset = 0;

	if(ret == true)
	{
		*width = info.width;
		*height = info.height;
		*standard = info.standard;
		return true;
	}
	*standard = UNKNOWN_TYPE;
	*width = 0;
	*height = 0;
	return false;
}

u32 _read_word_little(unsigned char* buffer)
{
	return (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
}


u32 avi_parse(u32  buffer_start_addr, u32  buffer_size,
							   u8* src_mem,  u32* frame_start_addr,   u32* frame_size, u32* consumed_frame_size)
{	
	unsigned int position = 0;

	while((position + 8) <= buffer_size)
	{	
		unsigned int dwSize;
		unsigned char FourCC[4];
		
		get_fourcc1(&src_mem[position], FourCC);
		position += 4;
		
		if(compare_fourcc(FourCC, "RIFF") || compare_fourcc(FourCC, "LIST"))
		{
			dwSize = _read_word_little(&src_mem[position]) - 4;
			position += 4;
			
			get_fourcc1(&src_mem[position], FourCC);		
			position += 4;
		}
		else if(FourCC[2] == 'd')
		{
			dwSize = _read_word_little(&src_mem[position]);
			position += 4;

			*frame_start_addr = buffer_start_addr + position;
			*frame_size = dwSize;
			if(dwSize%2 == 1) 
			{
				dwSize++;
			}
			*consumed_frame_size = dwSize;
			position += dwSize;
			
			if(dwSize > 0)
			{
				if(position > buffer_size)
					return 1;
				return 0;
			}
		}
		else if(FourCC[2] == 'w')
		{
			dwSize = _read_word_little(&src_mem[position]);
			if(dwSize%2 == 1)
			{
				dwSize++;
			}
			position += dwSize + 4;

		}
		else
		{
			dwSize = _read_word_little(&src_mem[position]);
			//DS
			if(dwSize%2 == 1)
			{
				dwSize++;
			}
			//~DS
			position += dwSize + 4;
		}

		if(position >= buffer_size)
			return 1;
	}	
	return 2;	
}
