Слияние кода завершено, страница обновится автоматически
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <config.h>
#include <disp_manager.h>
#include <video_manager.h>
#include <convert_manager.h>
#include <typedef.h>
#include <error.h>
#include <render.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SIMU_PORT 8000 //仿真接口的端口号
#define MAX_BUF_LEN 2048
#define NET_BLOCK 0 //阻塞方式
#define NET_NONBLOCK 0xff //非阻塞方式
/******************************************************************************
* 函数: net_udp_init
* 功能: UDP初始化
* 参数: port - UDP端口号
timeout - 发送接收阻塞模式下超时时间
* 返回: >0 - 成功 返回UDP的socket号
-ERR_SYS - 系统错误
-ERR_INVAL - 接口错误
-ERR_BUSY - 已断开
* 说明: 无
******************************************************************************/
int net_udp_init(u16 port, u16 timeout)
{
int ret;
int sockfd;
struct sockaddr_in sockaddr_udp;
int optval = 1;
struct timeval tout;
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -ERR_SYS)
{
ret = -ERR_SYS;
goto error;
}else
{
sockaddr_udp.sin_family = AF_INET;
sockaddr_udp.sin_port = htons(port);
sockaddr_udp.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY 表示所有计算机都能连过来
memset(&(sockaddr_udp.sin_zero), 0, 8);
//设置超时
if (timeout != 0xffff)
{
//设置网络阻塞接收、发送超时时间
tout.tv_sec = timeout;
tout.tv_usec = 0;
//设置发送超时
ret = setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tout, sizeof(tout));
if (ret)
{
ret = -ERR_SYS;
goto error;
}
//设置接收超时
ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tout, sizeof(tout));
if(ret)
{
ret = -ERR_SYS;
goto error;
}
}
//设置端口复用
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,(char *)&optval,sizeof(optval)) != 0)
{
ret = -ERR_INVAL;
goto error;
}
if (bind(sockfd, (struct sockaddr *)&sockaddr_udp, sizeof(struct sockaddr)) == -ERR_SYS)
{
ret = -ERR_INVAL;
goto error;
}
}
ret = sockfd;
error:
return ret;
}
/******************************************************************************
* 函数: net_udp_send
* 功能: UDP发送数据
* 参数: sockfd - UDP端口号
buf - 数据缓冲区
length - 要发送数据长度
ip - 目标IP地址
port - 目标端口号
* 返回: >0 - 成功发送数据字节数
-ERR_SYS - 系统错误
-ERR_INVAL - 接口错误
-ERR_BUSY - 已断开
* 说明: 无
******************************************************************************/
int net_udp_send(int sockfd, u8 *buf, u16 length, u8 *ip, u16 port)
{
int ret;
struct sockaddr_in dest_addr; //要发送的地址
if(length == 0)
{
ret = -ERR_INVAL;
goto error;
}
//设置参数
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
//dest_addr.sin_addr.s_addr = inet_addr(ip);
memcpy(&dest_addr.sin_addr.s_addr , ip , 4);
memset(&(dest_addr.sin_zero), 0, 8);
ret = sendto(sockfd, buf, length, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
if(ret == -ERR_SYS)
{
if((errno == EPIPE) || (errno == EDESTADDRREQ) || (errno == EBADF))
{
ret = -ERR_DISCONNECT;
}else
{
ret = -ERR_TIMEOUT;
}
goto error;
}
error:
return (ret);
}
/******************************************************************************
* 函数: net_udp_recv
* 功能: UDP接收数据
* 参数: sockfd - UDP端口号
buf - 数据缓冲区(返回)
max_length - 数据缓冲区最大长度
length - 实际接收数据长度(返回)
ip - 源地址IP地址(返回)
port - 源地址端口号(返回)
* 返回: 0 - 成功
-ERR_SYS - 系统错误
-ERR_INVAL - 接口错误
-ERR_BUSY - 已断开
* 说明: 无
******************************************************************************/
int net_udp_recv(int sockfd, u8 *buf, u16 max_length, u32 *length, u8 flag, u8 *ip, u16 *port)
{
int ret, recvbytes;
struct sockaddr_in dest_addr;
socklen_t len;
len = sizeof(struct sockaddr);
switch(flag)
{
case NET_NONBLOCK: //非阻塞方式接收数据
recvbytes = recvfrom(sockfd, buf, max_length, MSG_DONTWAIT, (struct sockaddr *)&dest_addr, &len);
break;
case NET_BLOCK: //阻塞方式接收数据
recvbytes = recvfrom(sockfd, buf, max_length, 0, (struct sockaddr *)&dest_addr, &len);
break;
default:
ret = -ERR_INVAL;
break;
}
if((recvbytes != -ERR_SYS) && (recvbytes != 0))
{
memcpy(length, &recvbytes, 4);//接收数据长度
}else if(recvbytes == 0)
{
ret = -ERR_DISCONNECT;
goto error;
}else
{
if(errno == EAGAIN)
{
ret = -ERR_TIMEOUT;
}else
{
ret = -ERR_SYS;
}
goto error;
}
*port = ntohl(dest_addr.sin_port); //源地址端口号
//ipaddr = (char *)inet_ntoa(dest_addr.sin_addr.s_addr);
memcpy(ip, &(dest_addr.sin_addr.s_addr), 4);//源地址IP地址
ret = 0;
error:
return (ret);
}
/* video2lcd </dev/video0,1,...> */
int main(int argc, char **argv)
{
// unsigned char test = 0;
int ret;
int sockfd = 0x00;
int iError;
T_VideoDevice tVideoDevice;
PT_VideoConvert ptVideoConvert;
int iPixelFormatOfVideo;
int iPixelFormatOfDisp;
PT_VideoBuf ptVideoBufCur;
T_VideoBuf tVideoBuf;
T_VideoBuf tConvertBuf;
T_VideoBuf tZoomBuf;
T_VideoBuf tFrameBuf;
int iLcdWidth;
int iLcdHeight;
int iLcdBpp;
int iTopLeftX;
int iTopLeftY;
float k;
uint16_t timeout = 0xFFFF;
u8 ipaddr[4] = {192,168,1,100};
if (argc != 2)
{
printf("Usage:\n");
printf("%s </dev/video0,1,...>\n", argv[0]);
return -1;
}
/*network init*/
ret = net_udp_init(SIMU_PORT, timeout);
if(ret < 0){
DBG_PRINTF("net_udp_init error!\n");
return -1;
}else{
sockfd = ret;
}
/* 一系列的初始化 */
/* 注册显示设备 */
DisplayInit();
/* 可能可支持多个显示设备: 选择和初始化指定的显示设备 */
SelectAndInitDefaultDispDev("fb");
GetDispResolution(&iLcdWidth, &iLcdHeight, &iLcdBpp);
GetVideoBufForDisplay(&tFrameBuf);
iPixelFormatOfDisp = tFrameBuf.iPixelFormat;
VideoInit();
iError = VideoDeviceInit(argv[1], &tVideoDevice);
if (iError)
{
DBG_PRINTF("VideoDeviceInit for %s error!\n", argv[1]);
return -1;
}
iPixelFormatOfVideo = tVideoDevice.ptOPr->GetFormat(&tVideoDevice);
VideoConvertInit();
ptVideoConvert = GetVideoConvertForFormats(iPixelFormatOfVideo, iPixelFormatOfDisp);
if (NULL == ptVideoConvert)
{
DBG_PRINTF("can not support this format convert\n");
return -1;
}
/* 启动摄像头设备 */
iError = tVideoDevice.ptOPr->StartDevice(&tVideoDevice);
if (iError)
{
DBG_PRINTF("StartDevice for %s error!\n", argv[1]);
return -1;
}
memset(&tVideoBuf, 0, sizeof(tVideoBuf));
memset(&tConvertBuf, 0, sizeof(tConvertBuf));
tConvertBuf.iPixelFormat = iPixelFormatOfDisp;
tConvertBuf.tPixelDatas.iBpp = iLcdBpp;
memset(&tZoomBuf, 0, sizeof(tZoomBuf));
//PutTest();
while (1)
{
// char buf[255];
// FILE *fp;
// time_t ts;
// struct tm *t;
// time(&ts);
// t = gmtime(&ts);
// sprintf(buf, "video-%d-%d-%d--%02d-%02d-%02d.jpg",t->tm_year,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
// fp = fopen(buf,"w");
// if(fp == NULL)
// {
// DBG_PRINTF("fopen file error!\n");
// return -1;
// }
/* 读入摄像头数据 */
iError = tVideoDevice.ptOPr->GetFrame(&tVideoDevice, &tVideoBuf);
if (iError)
{
DBG_PRINTF("GetFrame for %s error!\n", argv[1]);
return -1;
}
ptVideoBufCur = &tVideoBuf;
// DBG_PRINTF("ptVideoBufCur->tPixelDatas.iWidth:%d ptVideoBufCur->tPixelDatas.iHeight:%d total:%d\n",ptVideoBufCur->tPixelDatas.iWidth,ptVideoBufCur->tPixelDatas.iHeight,ptVideoBufCur->tPixelDatas.iTotalBytes);
// fwrite(tVideoBuf.tPixelDatas.aucPixelDatas,tVideoBuf.tPixelDatas.iTotalBytes,1,fp);
// fclose(fp);
ret = net_udp_send(sockfd, tVideoBuf.tPixelDatas.aucPixelDatas, tVideoBuf.tPixelDatas.iTotalBytes, ipaddr, 9000);
if(ret < 0)
{
DBG_PRINTF("net_udp_send error!\n");
}
if (iPixelFormatOfVideo != iPixelFormatOfDisp)
{
/* 转换为RGB */
iError = ptVideoConvert->Convert(&tVideoBuf, &tConvertBuf);
DBG_PRINTF("Convert %s, ret = %d\n", ptVideoConvert->name, iError);
if (iError)
{
DBG_PRINTF("Convert for %s error!\n", argv[1]);
return -1;
}
ptVideoBufCur = &tConvertBuf;
}
//DBG_PRINTF("ptVideoBufCur->tPixelDatas.iWidth:%d ptVideoBufCur->tPixelDatas.iHeight:%d\n",ptVideoBufCur->tPixelDatas.iWidth,ptVideoBufCur->tPixelDatas.iHeight);
/* 如果图像分辨率大于LCD, 缩放 */
if (ptVideoBufCur->tPixelDatas.iWidth > iLcdWidth || ptVideoBufCur->tPixelDatas.iHeight > iLcdHeight)
{
/* 确定缩放后的分辨率 */
/* 把图片按比例缩放到VideoMem上, 居中显示
* 1. 先算出缩放后的大小
*/
k = (float)ptVideoBufCur->tPixelDatas.iHeight / ptVideoBufCur->tPixelDatas.iWidth;
tZoomBuf.tPixelDatas.iWidth = iLcdWidth;
tZoomBuf.tPixelDatas.iHeight = iLcdWidth * k;
if ( tZoomBuf.tPixelDatas.iHeight > iLcdHeight)
{
tZoomBuf.tPixelDatas.iWidth = iLcdHeight / k;
tZoomBuf.tPixelDatas.iHeight = iLcdHeight;
}
tZoomBuf.tPixelDatas.iBpp = iLcdBpp;
tZoomBuf.tPixelDatas.iLineBytes = tZoomBuf.tPixelDatas.iWidth * tZoomBuf.tPixelDatas.iBpp / 8;
tZoomBuf.tPixelDatas.iTotalBytes = tZoomBuf.tPixelDatas.iLineBytes * tZoomBuf.tPixelDatas.iHeight;
if (!tZoomBuf.tPixelDatas.aucPixelDatas)
{
tZoomBuf.tPixelDatas.aucPixelDatas = malloc(tZoomBuf.tPixelDatas.iTotalBytes);
}
PicZoom(&ptVideoBufCur->tPixelDatas, &tZoomBuf.tPixelDatas);
ptVideoBufCur = &tZoomBuf;
}
/* 合并进framebuffer */
/* 接着算出居中显示时左上角坐标 */
iTopLeftX = (iLcdWidth - ptVideoBufCur->tPixelDatas.iWidth) / 2;
iTopLeftY = (iLcdHeight - ptVideoBufCur->tPixelDatas.iHeight) / 2;
PicMerge(iTopLeftX, iTopLeftY, &ptVideoBufCur->tPixelDatas, &tFrameBuf.tPixelDatas);
FlushPixelDatasToDev(&tFrameBuf.tPixelDatas);
//FlushPixelDatasToDev(&ptVideoBufCur->tPixelDatas);
iError = tVideoDevice.ptOPr->PutFrame(&tVideoDevice, &tVideoBuf);
if (iError)
{
DBG_PRINTF("PutFrame for %s error!\n", argv[1]);
return -1;
}
//fclose(fp);
/* 把framebuffer的数据刷到LCD上, 显示 */
}
return 0;
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )