www.pudn.com > Net_apps.rar > HttpStream.c
//*************************************************************
// Copyright 2003 Service & Quality Technology CO., LTD.
// ALL RIGHTS RESERVED.
// This software is provided under license and contains proprietary
// and confidential material which is the property of SQ tech.
//
// FileName : HttpStream.c
// Description : send audio video
// Reversion : 0.1 ,Date : 2004/03/18 ,Author : gofly
// Comment : first implementation
//
//*************************************************************
#include "opt.h"
//Panda Add
//Begin
//#include "..\drive\fs\md_fs.h"
//End
#if HTTP_OPEN
#include "..\include\L3\net_apps\httpd\api\HttpStream.h"
#include "..\include\L3\net_apps\httpd\html\audio.h"
#include "..\include\L0\video\detection.h"
#include "..\include\L2\system\24c08.h"
#include "..\include\L3\back_image\bgimg.h" //add by jgy
#include "..\include\L3\gpio\sd_q.h" //add by jgy 10/11/05
THttpStreamCtrlBlack GtHSCB;
extern OS_EVENT *BackGetImgEvenSem;
INT8U M1count=0; /*multione counter for one image by jjl*/
JPG_BUF *M1p;
#define FPS_IDLE 3 //add by jgy 8/24/05 when no motion detected, send images of FPS_IDLE per second
/*
0x0a,0x0a,0x2d,0x2d,0x6d,0x79,0x62,0x6f,0x75,0x6e,0x64,
0x61,0x72,0x79,0x0a,
*/
/*
char Video_Jpg_Sample_Head[]={
0x2a,0x2a,0x2a,0x2a, //magic number **** 4 bytes
//0x16,0x00, // head size = 4+2+4+1+2+2+1+1+1+1+1+2=22=0x16 2 bytes
0xbc,0x46,0x00,0x00, // bitstream size sizeof(jpg) 4 bytes
0x02,//320*240 // 0x01 160*120 0x02 320*240 0x04 640*480 1 bytes
0x46,0x00, //qtable 2 bytes
0xd3,0x07, //
0x0a, //る
0x14, //ら
0x01, //
0x02, //だ
0x03, //
0x6b,0x03, //睝
} ;
*/
//---- 20bytes---//
char Video_Jpg_Sample_Head[]=
{
0x2a,0x2a, //magic number *
0xbc,0x46,0x00,0x00, // jpg size
0x00,0x00, // jpg width
0x00,0x00, // jpg height
0x46, // qtable
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
//***********************************************
// StreamAdd(void *data)
// Description : add socket to GtHSCB(http stream ctrl black)
// and clear socket in HCB(http ctrl black)
// Parameters :
// Returns :
//***********************************************
INT8U StreamAdd(void *data, INT8U index)
{
INT8U i;
static INT16U pid = 2000;
THttpStreamCtrlBlack *ptHSCB = &GtHSCB;
THttpCtrlBlack *ptHCB = data ;
for(i = 0; i < HTTP_MAX_STREAM_IMAGE ; i++)
{
if(ptHSCB->PID[i] == 0xff) break;
}
if(HTTP_MAX_STREAM_IMAGE == i)
return HTTP_R_ERR;
if(!strncmp("/cgi-bin/Stream?Video", ptHCB->Order[index], 21))
{
ptHSCB->AccessTime[i] = OSTimeGet();
ptHSCB->type[i] = HTTP_STREAM_VIDEO;
ptHSCB->Sock[i] = ptHCB->Sock[index];
pid = pid++;
HttpClearHCBByIndex((void*)data, index);
ptHSCB->PID[i] = pid;
ptHSCB->Stat[i] = HTTP_STREAM_STAT_NEW;
if(pid > 3000) pid = 2000; // pid = 2000 ~ 3000
return HTTP_R_OK;
}
else
{
return HTTP_R_ERR; // to bring about sock destory
}
}
//***********************************************
// HttpStream(void *data)
// Description : send audio video
// Parameters :
// Returns :
//***********************************************
void HttpStream(void *data)
{
INT8U i;
INT8U count = 0;
struct timeval timeout={1,0};
fd_set writeset;
INT8U maxfdp1;
INT32S len;
INT32S SendLen;
THttpStreamCtrlBlack *ptHSCB = &GtHSCB;
HttpStreamInit((void*)ptHSCB);
while(1)
{
FD_ZERO(&writeset);
for(i = 0, count = 0; i < HTTP_MAX_STREAM_IMAGE; i++)
{
if(ptHSCB->PID[i] != 0xff &&
(ptHSCB->Stat[i] == HTTP_STREAM_STAT_NEW ||
ptHSCB->Stat[i] == HTTP_STREAM_STAT_SEN)
)
{
ptHSCB->Stat[i] = HTTP_STREAM_STAT_SEN;
FD_SET(ptHSCB->Sock[i], &writeset);
count++;
if( maxfdp1 < ptHSCB->Sock[i] + 1)
maxfdp1 = ptHSCB->Sock[i] + 1;
}
} /*for(i = 0, count = 0; i < HTTP_MAX_SOCKET; i++)*/
if(count == 0)
{
OSTimeDlyHMSM(0, 0, 0, 5);
continue;
}
select(maxfdp1, 0, &writeset, 0,&timeout);
for(i = 0; i < HTTP_MAX_STREAM_IMAGE; i++)
{
if(ptHSCB->Sock[i] == INVALID_SOCKET
|| ptHSCB->Stat[i] != HTTP_STREAM_STAT_SEN)
continue;
if( FD_ISSET(ptHSCB->Sock[i], &writeset) )
{
GoToSendStream:
ptHSCB->AccessTime[i] = OSTimeGet();
len = 0;
if(ptHSCB->File[i] != NULL)
{
SendLen = ptHSCB->TotalLen[i] - ptHSCB->SendLen[i];
if(count >= 3)
{
SendLen = min(SendLen, 1460);
}
else if(SendLen >1460)
{
SendLen = min(SendLen ,
TCP_SND_BUF-socket_check_sendbuf(ptHSCB->Sock[i])) ;
SendLen = (SendLen/1460)*1460;
}
len = send(ptHSCB->Sock[i]
,ptHSCB->File[i] + ptHSCB->SendLen[i]
,SendLen
,0);
//----- gofly debug-------
//ptHSCB->SendLen[i] = 0;
//while(1){
//printf("%p %d %d \n",ptHSCB->File[i] + ptHSCB->SendLen[i],len);
//ptHSCB->SendLen[i] += 1024;
//}
//--------- gofly debug
//if((len % 1460))
// printf("%d %d %d %d %d \n",i,len , socket_check_sendbuf(ptHSCB->Sock[i]));
/*
len = send(ptHSCB->Sock[i]
,ptHSCB->File[i] + ptHSCB->SendLen[i]
,ptHSCB->TotalLen[i] - ptHSCB->SendLen[i]
,0);
*/
ptHSCB->SendLen[i] += len;
}
if(len < 0)
{ //send destory
HttpCloseStreamConnect((void*)ptHSCB, i);
continue;
}
if(ptHSCB->SendLen[i] == ptHSCB->TotalLen[i])
{
if(ptHSCB->File[i] != NULL && ptHSCB->TotalLen1[i] != 0)
{
ptHSCB->File[i] = ptHSCB->File[i] + ptHSCB->TotalLen[i];
ptHSCB->TotalLen[i] = ptHSCB->TotalLen1[i];
ptHSCB->TotalLen1[i] = 0;
ptHSCB->SendLen[i] = 0;
}
else
{
//--- free image
if(ptHSCB->File[i] != NULL)
{
#if VIDEO_FREE
video_image_free(&ptHSCB->send_jpg[i]);
#endif
}
//--- get image
HttpGetImage((void*)ptHSCB, i);
}
}
}
else
{ // check timeout
if(OSTimeGet() - ptHSCB->AccessTime[i] > HTTP_SOCK_IDLE_TIMEOUT)
{
HttpCloseStreamConnect((void*)ptHSCB, i);
continue;
}
}/*if( FD_ISSET(ptHSCB->Sock[i], &writeset) )*/
}
}/* while(1)*/
}
//***********************************************
// HttpStreamInit(void *data)
// Description : INIT GtHSCB
// Parameters :
// Returns :
//***********************************************
void HttpStreamInit(void *data)
{
INT8U i;
THttpStreamCtrlBlack *ptHSCB = &GtHSCB;
for(i = 0; i < HTTP_MAX_STREAM_IMAGE; i++)
{
HttpClearHSCBByIndex((void *)ptHSCB, i);
}
}
//***********************************************
// HttpClearHSCBByIndex(void *data, INT8U index)
// Description : INIT GtHSCB
// Parameters :
// Returns :
//***********************************************
void HttpClearHSCBByIndex(void *data, INT8U index)
{
THttpStreamCtrlBlack *ptHSCB = (INT8U *)data ;
ptHSCB->Sock[index] = INVALID_SOCKET;
ptHSCB->Stat[index] = HTTP_STREAM_STAT_CLO;
ptHSCB->type[index] = HTTP_STREAM_NULL;
ptHSCB->AccessTime[index] = 0;
ptHSCB->TotalLen[index] = 0;
ptHSCB->TotalLen1[index] = 0;
ptHSCB->SendLen[index] = 0;
ptHSCB->File[index] = NULL;
ptHSCB->PID[index] = 0xff;
ptHSCB->send_jpg[index].jpg_file = NULL;
}
//***********************************************
//void HttpCloseConnect(void *data, INT8U index)
// Description : close http clinet socket
// Parameters :
// Returns :
//
//***********************************************
void HttpCloseStreamConnect(void *data, INT8U index)
{
char Msg[256];
THttpStreamCtrlBlack *ptHSCB = data ;
sprintf(Msg, "HTTP HttpCloseStreamConnect PID %d\n", ptHSCB->PID[index]);
close(ptHSCB->Sock[index]);
SHOW_EX1(HTTP_DEBUG, Msg);
if(ptHSCB->File[index] != NULL)
{
video_image_free(&ptHSCB->send_jpg[index]);
}
//imgmax[index] = 0;
//printf("out stream");
HttpClearHSCBByIndex((void*)data, index);
}
//***********************************************
//void HttpGetImage(void *data, INT8U index)
// Description : get image
// Parameters :
// Returns :
//
//***********************************************
void HttpGetImage(void *data, INT8U index)
{
SVideoJpgHead extra_head;
//JPG_BUF send_jpg;
THttpStreamCtrlBlack *ptHSCB = data ;
INT16U Width = atoi(IoW(NULL, NULL, IOR, ROOT));
INT16U Height = atoi(IoH(NULL, NULL, IOR, ROOT));
INT16U Qual = atoi(IoImgSet("IMG_S_GET_C", NULL, IOR, ROOT));
//set image information
ptHSCB->send_jpg[index].jpg_imag_width = Width;
ptHSCB->send_jpg[index].jpg_imag_height = Height;
ptHSCB->send_jpg[index].jpg_qual = Qual;
ptHSCB->send_jpg[index].jpg_shp_smooth = 0; //disable shp & smooth
ptHSCB->send_jpg[index].jpg_wait_msec = 0; //always wait image get
video_image_get((void*)&ptHSCB->send_jpg[index]);
memcpy((char*)&extra_head, (char*)Video_Jpg_Sample_Head, 20);
extra_head.Jpg_Size = ptHSCB->send_jpg[index].jpg_size;
extra_head.Qtable = ptHSCB->send_jpg[index].jpg_qual;
extra_head.Width = ptHSCB->send_jpg[index].jpg_imag_width ;
extra_head.Height = ptHSCB->send_jpg[index].jpg_imag_height ;
ptHSCB->File[index] = ptHSCB->send_jpg[index].jpg_line;
ptHSCB->TotalLen[index] = ptHSCB->send_jpg[index].jpg_size + 20;
ptHSCB->SendLen[index] = 0;
memcpy(ptHSCB->send_jpg[index].jpg_line, &extra_head , 20);
}
//***********************************************
//void HttpGetImage_20040712(void *data, INT8U index)
// Description : get image 盢 stream 硂task
// httpthread task ず
// Parameters :
// Returns :
//
//***********************************************
#if MULTIONE
void HttpGetImage_MultiOne(THttpCtrlBlack *ptHCB, INT8U index)
{
int i,j=0;
INT8U *img_resP,*img_resN;
for (i=0;i j
}
if (!M1count) //if Micount =0 get new image
{
M1count++;
video_image_get((void*)&ptHCB->send_jpg[index]);
M1p = &ptHCB->send_jpg[index];
}
else if (M1count<=j) //if Micount <=j not greater than connect num use prev image
{
M1count++;
ptHCB->send_jpg[index] = *M1p;
}
else if (M1count > j) //if greater than connect num free image and get new
{
M1count=1;
video_image_free(M1p);
for (i=0;i<8;i++)
{
ptHCB->send_jpg[i] = *M1p;
}
video_image_get((void*)&ptHCB->send_jpg[index]);
M1p = &ptHCB->send_jpg[index];
}
return;
//video_image_get(jpeg_inf);
//return;
}
#endif
void HttpGetImage_20040712(void *data, INT8U index)
{
//Panda Add
//Begin
// MDSAVEINF iMDSaveInf;
//End
JPG_FILLDATA *jpg_filldata;
JPG_DIS_CHAR *jpg_dis_char;
//SVideoJpgHead extra_head;
//JPG_BUF send_jpg;
THttpCtrlBlack *ptHCB = data ;
//static INT16S imgTime;
static INT32U imgTime;
static INT8U IgnoreImgCount;
u8_t fps;
//INT16U Width = atoi(IoW(NULL, NULL, IOR, ROOT));
//INT16U Height = atoi(IoH(NULL, NULL, IOR, ROOT));
//INT16U Qual = atoi(IoImgSet("IMG_S_GET_C", NULL, IOR, ROOT));
//set image information
//ptHCB->send_jpg[index].jpg_imag_width = Width;
//ptHCB->send_jpg[index].jpg_imag_height = Height;
//ptHCB->send_jpg[index].jpg_qual = Qual;
//ptHCB->send_jpg[index].jpg_shp_smooth = 0; //disable shp & smooth
//ptHCB->send_jpg[index].jpg_wait_msec = 0; //always wait image get
#if MULTIONE
HttpGetImage_MultiOne(ptHCB,index);
#else
//video_image_get((void*)&ptHCB->send_jpg[index]);
if(video_bkimage_get(ptHCB, index) != 0)
{
return;
}
if (Sd_trigger_Hotkey)
{
Sd_trigger_Hotkey = 0;
md_write_data(&ptHCB->send_jpg[index]);
}
#endif
//add by jgy 8/24/05
//空闲时帧率控制
if(!Ply_flag)
{//上传数据时不加帧率控制
if((eprom_ptos.eprom_opt_trigger.motin_det1 == TRUE) || (eprom_ptos.eprom_opt_trigger.motin_det2 == TRUE))
{
if(detection_ctrl.md_warning_count[0] == 0 && detection_ctrl.md_warning_count[1] == 0)
{
//if(ptHCB->send_jpg[index].jpg_time.tm_sec == imgTime)
if(OSTimeGet() - imgTime <= OS_TICKS_PER_SEC)
{//malipulate in a second
IgnoreImgCount++;
switch(ptHCB->send_jpg[index].jpg_imag_width)
{
case 640: //640 X 480
fps = 10 - 1; //subtract 1 for network transfer quality, may range from 1(best) to 7(worst)
break;
case 320: //320 X 240
fps = 25 - 2; //subtract 1 for network transfer quality, may range from 1(best) to 12(worst)
break;
default: //160 X 120
fps = 30 - 3; //subtract 1 for network transfer quality, may range from 1(best) to 15(worst)
break;
}
if(IgnoreImgCount < fps / FPS_IDLE)
{
//video_image_free(&ptHCB->send_jpg[index]);
video_bkimage_free(data, index);
//memset(&ptHCB->send_jpg[index], 0, sizeof(JPG_BUF));
return;
}
//IgnoreImgCount = 0;
}
}
}
}
//jgy++
//memcpy((char*)&extra_head, (char*)Video_Jpg_Sample_Head, 20);
//extra_head.Jpg_Size = ptHCB->send_jpg[index].jpg_size;
//extra_head.Qtable = ptHCB->send_jpg[index].jpg_qual;
//extra_head.Width = ptHCB->send_jpg[index].jpg_imag_width ;
//extra_head.Height = ptHCB->send_jpg[index].jpg_imag_height;
jpg_filldata = ptHCB->send_jpg[index].jpg_file->fill_data;
jpg_filldata->link_count = index;
//add by jgy 10/25/05
jpg_dis_char = jpg_filldata->jpg_dis_char;
if(Rec_flag)
{//正在录制当前影像
jpg_dis_char[1].char_len = 4;
jpg_dis_char[1].char_line = 1; //2nd line
jpg_dis_char[1].char_mod = 1; //right
jpg_dis_char[1].char_color = 0; //red
sprintf(jpg_dis_char[1].char_word, "REC ");
}
else if(Ply_flag)
{
jpg_dis_char[1].char_len = 13;
jpg_dis_char[1].char_line = 2;
jpg_dis_char[1].char_mod = 1;
jpg_dis_char[1].char_color = 2; //blue
sprintf(jpg_dis_char[1].char_word, "UPLOADING... ");
}
//jgy++
ptHCB->File[index] = ptHCB->send_jpg[index].jpg_line;
ptHCB->TotalLen[index] = ptHCB->send_jpg[index].jpg_size + 20;
ptHCB->SendLen[index] = 0;
ptHCB->FileType[index] = FILE_TYPE_STREAM;
IgnoreImgCount = 0;
//imgTime = ptHCB->send_jpg[index].jpg_time.tm_sec; //add by jgy 8/25/05
imgTime = OSTimeGet(); //modified by jgy 10/6/05
//Panda Add
//Begin
//iMDSaveInf.jpeg_inf=&(ptHCB->send_jpg[index]);
//md_write_data(&iMDSaveInf);
//End
}
void HttpGetHistImage(void *data, INT8U index)
{
THttpCtrlBlack *ptHCB = data;
SD_RING_ELM sd_jpg_inf;
JPG_FILLDATA *jpg_filldata;
//static BOOLEAN buf_empty = FALSE;
if(!hist_video_blk.rdy) //历史图片还没有准备好
return;
//if(buf_empty == TRUE)
//{
// buf_empty = FALSE;
// OSSemPost(sd_snd_Sem);
//}
if(SD_Q_FAIL == sd_Q_GetImage(&sd_jpg_inf))
{//图片发送队列已空,给sd卡任务发信号量
hist_video_blk.rdy = 0;
OSSemPost(sd_snd_Sem);
return;
}
//if(sd_jpg_inf.lst_img == TRUE)
// buf_empty = TRUE;
jpg_filldata = sd_jpg_inf.jpg_file->fill_data;
jpg_filldata->link_count = index; //保留作断点续传时用
ptHCB->File[index] = sd_jpg_inf.jpg_line;
ptHCB->TotalLen[index] = sd_jpg_inf.jpg_size + 20;
ptHCB->SendLen[index] = 0;
ptHCB->FileType[index] = FILE_TYPE_STREAM;
}
#endif /*HTTP_OPEN*/