////////=======================================================================
///sample of get connection and start receive data from socket.
////////=======================================================================


DWORD CALLBACK GetVideoThreadFunc( void* pArguments )
{
	char recvbuf[MAX_RECV_SIZE]={0};
	CViewerControl *pHttp = (CViewerControl*)pArguments;
	int len_inet;
	struct hostent *host_ip;
	char ip_addr[128]={0};
    struct in_addr ServerAddr;
    struct sockaddr_in AddrSrvr;/* AF_INET */
	int timeout=120;	
	char cmd[256];
	char cmdbuf[512]={0};
	int recv_size=0;

		sprintf(cmd,"/video.vdo?action=live&");
		for(int i=1;i<=pHttp->m_iMaxChannel;i++){
			char tmp[10]; 
			sprintf(tmp,"ch%d=1&",i);
			strcat(cmd,tmp);
		}
		strcat(cmd,"THREAD_ID=");
		strcat(cmd,pHttp->m_sThreadID.c_str());
	OutputDebugStringA(cmd);
	
		wcstombs(ip_addr,pHttp->m_bstrWebSite,pHttp->m_bstrWebSite.Length());
	for (unsigned int i=0;i<strlen(ip_addr);i++ ) {
		if ( ip_addr[i] == ':' ) {
			ip_addr[i] = 0x00;
		    break;
	    }
	}
	if(strlen(ip_addr)==0){
		goto video_exit;
	}
	// get ip end
	//////////////////////////////////////////////////////////////////////
	sprintf(cmdbuf,	"GET %s HTTP/1.1\n"
					"Accept: */*\n"
					"Accept-Encoding: gzip, deflate\n"
					"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)\n"
					"Host: %s:%d\n"
					"Connection: Keep-Alive\n"
					"Cache-Control: no-cache\n"
					"\r\n\r\n"
					,cmd,ip_addr,pHttp->m_iPort);

	host_ip = gethostbyname(ip_addr);
	if (host_ip->h_addrtype != AF_INET)return -1;
	
	OutputDebugStringA("h_addrtype==AF_INET" );
	strcpy(ip_addr, inet_ntoa( *(struct in_addr *)host_ip->h_addr_list[0]));
	
	ServerAddr.S_un.S_addr = inet_addr(ip_addr);

	if (ServerAddr.S_un.S_addr == INADDR_NONE)return -1;
	 
	// connect to dvr
    memset(&AddrSrvr,0,sizeof(AddrSrvr));
    AddrSrvr.sin_family = AF_INET;
    AddrSrvr.sin_port = htons(pHttp->m_iPort);
    AddrSrvr.sin_addr.s_addr =  ServerAddr.S_un.S_addr;

    len_inet = sizeof(AddrSrvr);
    //videosocket = socket(PF_INET,SOCK_STREAM,0);
	pHttp->videosocket=(SOCKET)(-1);
	if ( (pHttp->videosocket = socket(PF_INET,SOCK_STREAM,0))== -1 ){
		OutputDebugStringA("videosocket == -1" );
		return -1;
	}

	if ( (connect(pHttp->videosocket,(SOCKADDR*) &AddrSrvr,len_inet)) == -1 ){
   		OutputDebugStringA("connect videosocket == -1" );
		closesocket(pHttp->videosocket);
		pHttp->videosocket=(SOCKET)(-1);	
		return -1;
	}	

	if(pHttp->NetSend(pHttp->videosocket,cmdbuf,strlen(cmdbuf))<0){
		/*shutdown(pHttp->videosocket,SD_BOTH );
		closesocket(pHttp->videosocket);
		pHttp->videosocket=(SOCKET)(-1);	
		return -1;*/
	}


	if (pHttp->RecvTimeout(pHttp->videosocket,timeout)>0 && !pHttp->m_bSetVideoThreadStop&&!pHttp->CloseTrd)
	{
		pHttp->m_bGetVideoThreadFunc=true;
		int recv_size=0;
		int tmpsize=0;
		OutputDebugStringA("==========start recv while" );
		while(!pHttp->CloseTrd)
		{	
			if(pHttp->RecvTimeout(pHttp->videosocket,timeout)>0 &&(recv_size = recv(pHttp->videosocket,recvbuf,MAX_RECV_SIZE,0))>0)
			{
			///recieve data from socket.	
			}
	}
video_exit:
	if(pHttp->videosocket!=(SOCKET)(-1))
	{
		shutdown(pHttp->videosocket,SD_BOTH );
		closesocket(pHttp->videosocket);
		pHttp->videosocket=(SOCKET)(-1);
	}
	pHttp->m_bGetVideoThreadFunc=false;
	OutputDebugStringA("1GetVideoThreadFunc end" );
	return 0;
} 
////////======================================================================




////////=======================================================================
///sample of parsing stream data 
////////=======================================================================


/////Image type
enum
{
	DB_TYPE_FAKE_DATA =0,
	DB_TYPE_MP4_I=1,
	DB_TYPE_MP4_P,
	DB_TYPE_MP4_B,
}; 

/////Limitation of Image size
#define IMAGE_BUFFER_SIZE 204800

typedef struct {
	unsigned char *pHdr;
	unsigned char *pSuperExtra;
	unsigned char *pBody;
}ImgBuf;


inline unsigned int bswap_32(unsigned int x)
{
	x= ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF);
	x= (x>>16) | (x<<16);
	return x;
}

inline unsigned short bswap_16(unsigned short x)
{
    x= (x>>8)|((x<<8));
	return x;
}
inline unsigned char DB_CalBacChksum(unsigned char  *header)
{
	unsigned char chksum=0;
	if( *header=='@' && (*(header+1)=='2'||*(header+1)=='6')){
		int i=0;
		while(i<tBasicIdxSized1)
		//for(int i=0;i < tBasicIdxSized1;++i)
			chksum ^= *(header+i++);
	}
	return chksum;
}

DWORD CALLBACK GetBufThreadFunc( void* pArguments )
{
	CViewerControl *pHttp = (CViewerControl*)pArguments;
	unsigned int offset=0,bodysize=0,ResetP=0,recbodysize=0;
	unsigned short tmpSuperExtraSize=0;
	int ch;
	short remain_int=108;
	bool Getheader=false;
	ImgBuf imgBuf;
	tHeader *pDist=NULL;
	tBigEndianHeader *pDist1=NULL;
				
	unsigned char* headeroffset=NULL,*Imageoffset=NULL;	
	bool readyreset=false;
	while(!pHttp->m_bGetVideoThreadFunc && !pHttp->CloseTrd)
	{
		Sleep(100);
	}
				
	bool nofreesize=false;	

	while(!pHttp->CloseTrd)
	{		
				
			Getheader=false;
			offset=0;
			imgBuf.pHdr=NULL;
			while((offset+tHeaderSize)<pHttp->remotebufsize){
				headeroffset=pHttp->pRemoteRead+offset;
				pDist=(tHeader*)headeroffset;
				pDist1=(tBigEndianHeader*)headeroffset;
				if(pHttp->CloseTrd)goto GetBuf_exit;
				if(pDist->Basic.Header2  == 0x32){
					if(pDist->Basic.Header1  == 0x40 
						&&(bodysize=pDist->Basic.Size) < IMAGE_BUFFER_SIZE
						&& pDist->Basic.Type <= DB_TYPE_MP4_B 
						&&pDist->Basic.Chksum == pHttp->DB_CalBacChksum((unsigned char*)&pDist->Basic))
						{
						Getheader=true;
						recbodysize=bodysize;
						break;
					}		
				} 
				else if(pDist1->Basic.Header2 == 0x36){
					if(pDist1->Basic.Header1 == 0x40  && pDist1->Basic.Type <= DB_TYPE_MP4_B
						&&(bodysize=pHttp->bswap_32(pDist1->Basic.Size))< IMAGE_BUFFER_SIZE
						&&pDist1->Basic.Chksum == pHttp->DB_CalBacChksum((unsigned char*)&pDist1->Basic)){
						tmpSuperExtraSize=pHttp->bswap_16(pDist1->Extra.SuperExtraSize);
						Getheader=true;
						recbodysize=bodysize;
						break;
					}
				
				}
					
				offset++;
			}
#if 1
			if(offset!=0)
			{
				char aa[20];
				sprintf(aa,"offset =%d\n",offset);
				OutputDebugStringA(aa);		
			}					
#endif
			if(Getheader){
				ch = pDist->Basic.Channel;
				ResetP=offset+tHeaderSize+tmpSuperExtraSize+bodysize;

				if(pDist1->Basic.Audio){
					if(tmpSuperExtraSize){
						if(pDist->Basic.Header2  == 0x36){
							((tBigEndianHeader*)imgBuf.pHdr)->Extra.SuperExtraSize=0;
						}
						else{
							((tHeader*)imgBuf.pHdr)->Extra.SuperExtraSize=0;
						}
						Imageoffset+=tmpSuperExtraSize;
					}
					imgBuf.pSuperExtra=NULL;
				}
				else{
					if(tmpSuperExtraSize){
						imgBuf.pSuperExtra = new unsigned char [tmpSuperExtraSize];
						memcpy(imgBuf.pSuperExtra,Imageoffset,tmpSuperExtraSize);
						Imageoffset+=tmpSuperExtraSize;
						
					}
					else
					{
						imgBuf.pSuperExtra = new unsigned char [tSuperExtraIdxSize];
						memset(imgBuf.pSuperExtra,0,tSuperExtraIdxSize);

						tmpSuperExtraSize=tSuperExtraIdxSize;
						if(pDist->Basic.Header2  == 0x36){
							((tBigEndianHeader*)imgBuf.pHdr)->Extra.SuperExtraSize=pHttp->bswap_16(tmpSuperExtraSize);
							((tSuperExtraIdx*)imgBuf.pSuperExtra)->remain_size=pHttp->bswap_32(remain_int);////96+12
						}
						else{
							((tHeader*)imgBuf.pHdr)->Extra.SuperExtraSize=tmpSuperExtraSize;
							((tSuperExtraIdx*)imgBuf.pSuperExtra)->remain_size=108;
						}
						memcpy(((tSuperExtraIdx*)imgBuf.pSuperExtra)->title,pHttp->ChTitle[ch],11);//superextra's title is 12 bytes, copy title which we can get from API
					}
				}
					if(bodysize){
						if(pDist1->Basic.Audio==1 && pDist1->Basic.Source != 1 && (bodysize==1000||bodysize==1024))
						{
							recbodysize=bodysize*pHttp->m_iMaxChannel;
							imgBuf.pBody =  (unsigned char*)::_aligned_malloc(recbodysize * sizeof(unsigned char), 16);//new unsigned char [recbodysize];
							memset(imgBuf.pBody,0,recbodysize);
							if(readyreset){//if readyreset, extra and body should memcpy directly. Becuase our RemoteBuf size is much larger than image size.
								memcpy(imgBuf.pBody+bodysize*pHttp->m_i20Div[pHttp->m_i1Div],Imageoffset,bodysize);	
								Imageoffset+=bodysize;
							}
							else{
								unsigned int bodyleft=pHttp->pRemoteEnd-Imageoffset;
								if(bodyleft>=bodysize){
									memcpy(imgBuf.pBody+bodysize*pHttp->m_i20Div[pHttp->m_i1Div],Imageoffset,bodysize);	
									if(bodyleft==bodysize){
										Imageoffset=pHttp->RemoteBuf;
										readyreset=true;
										OutputDebugStringA("bodyleft==bodysize");
									}
									else Imageoffset+=bodysize;
								}
								else{
									memcpy(imgBuf.pBody+bodysize*pHttp->m_i20Div[pHttp->m_i1Div],Imageoffset,bodyleft);	
									memcpy(imgBuf.pBody+bodysize*pHttp->m_i20Div[pHttp->m_i1Div]+bodyleft,pHttp->RemoteBuf,bodysize-bodyleft);	
									Imageoffset=pHttp->RemoteBuf+bodysize-bodyleft;
									OutputDebugStringA("super reset");
									readyreset=true;
								}
							}
							if(pDist->Basic.Header2  == 0x36)
								((tBigEndianHeader*)imgBuf.pHdr)->Basic.Size=pHttp->bswap_32(recbodysize);
							else
								((tHeader*)imgBuf.pHdr)->Basic.Size=recbodysize;
							bodysize=recbodysize;
							((tHeader*)imgBuf.pHdr)->Basic.Chksum = pHttp->DB_CalBacChksum((unsigned char*)imgBuf.pHdr);
						}//end of "if(pDist1->Basic.Audio==1 && pDist1->Basic.Source != 1 && (bodysize==1000||bodysize==1024))"
						else
						{
							imgBuf.pBody = (unsigned char*)::_aligned_malloc(bodysize * sizeof(unsigned char), 16);//new unsigned char [bodysize];
							if(readyreset)
							{
								memcpy(imgBuf.pBody,Imageoffset,bodysize);
								Imageoffset+=bodysize;
							}
							else
							{
								unsigned int bodyleft=pHttp->pRemoteEnd-Imageoffset;
								if(bodyleft>=bodysize){
									memcpy(imgBuf.pBody,Imageoffset,bodysize);
									if(bodyleft==bodysize){
										Imageoffset=pHttp->RemoteBuf;
										readyreset=true;
										OutputDebugStringA("bodyleft==bodysize body reset");
									}
									else Imageoffset+=bodysize;
								}
								else{
									memcpy(imgBuf.pBody,Imageoffset,bodyleft);
									memcpy(imgBuf.pBody+bodyleft,pHttp->RemoteBuf,bodysize-bodyleft);
									Imageoffset=pHttp->RemoteBuf+bodysize-bodyleft;
									readyreset=true;
									OutputDebugStringA("body reset");
								}
							}	// else readyreset
						}	//else pDist1->Basic.Audio==1&&(bodysize==1000||bodysize==1024
					}	// if(bodysize)
					else imgBuf.pBody=NULL;
						///////////////////////////////////////////////////////////////////recoreding code end/////
					switch(pDist->Basic.Audio)
					{
					case 1:
					////audio data
						if(hdr->Baisc.Source)
						{
							//for IP cma's audio, hdr.Basic.Channel shows what channel it belongs to.
						}
						else{
							//for Analog cma's audio.
						}
						break;
					case 0:
					///////////video data
						break;
					default:
						SAFE_DELETE(imgBuf.pBody);
						SAFE_DELETE(imgBuf.pSuperExtra);
						SAFE_DELETE(imgBuf.pHdr);		
					}
				}
			}
	}
GetBuf_exit:						
    return 0;
}
