Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7678780
  • 博文数量: 961
  • 博客积分: 15795
  • 博客等级: 上将
  • 技术积分: 16612
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-07 14:23
文章分类

全部博文(961)

文章存档

2016年(1)

2015年(61)

2014年(41)

2013年(51)

2012年(235)

2011年(391)

2010年(181)

分类: 嵌入式

2011-02-23 20:59:45

  1. /* 服务端程序 server.c */
  2. //WB

  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. #include <stdio.h>
  8. #include <sys/ioctl.h>
  9. #include <sys/mman.h>
  10. #include <stdlib.h>
  11. #include <linux/types.h>
  12. #include <linux/videodev.h>
  13. #include <setjmp.h>
  14. #include <string.h>
  15. #include <signal.h>
  16. #include <errno.h>
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include "convert.h"

  20. #include "../avc-src-0.14/avc/common/T264.h"

  21. #define SERVER_PORT 8888

  22. T264_t* m_t264;
  23. T264_param_t m_param;
  24. char* m_pSrc;
  25. char* m_pDst;
  26. int* m_lDstSize;
  27. char* m_pPoolData;


  28. #define USB_VIDEO "/dev/video0"
  29. int cam_fd;
  30. struct video_mmap cam_mm;/*视频内存映射*/
  31. /*包含摄像头的基本信息,例如设备名称、
  32. 支持的最大最小分辨率、信号源信息等*/
  33. struct video_capability cam_cap;
  34. /*亮度、对比度等和voide_mmap中的分辨率*/
  35. struct video_picture cam_pic;
  36. struct video_mbuf cam_mbuf;/*摄像头存储缓冲区的帧信息*/
  37. struct video_window win;/* 设备采集窗口参数*/
  38. char *cam_data = NULL;
  39. int nframe;

  40. void read_video(char *pixels,int w, int h)
  41. {
  42.   int ret;
  43.   int frame=0;
  44.   cam_mm.width = w;
  45.   cam_mm.height = h;
  46.  /* 对于单帧采集只需设置 frame=0*/
  47.   cam_mm.frame = 0;
  48.   cam_mm.format=VIDEO_PALETTE_YUV420P; //change by 091215

  49. /* 若调用成功,则激活设备真正开始一帧图像的截取,是非阻塞的*/
  50.   ret = ioctl(cam_fd,VIDIOCMCAPTURE,&cam_mm);
  51.   if( ret<0 ) {
  52.     printf("ERROR: VIDIOCMCAPTURE\n");
  53.   }
  54. /* 函数判断该帧图像是否截取完毕,成功返回表示截取完毕*/
  55.   ret = ioctl(cam_fd,VIDIOCSYNC,&frame);
  56.   if( ret<0 ) {
  57.     printf("ERROR: VIDIOCSYNC\n");
  58.   }
  59. }

  60. void config_vid_pic()
  61. {
  62.   char cfpath[100];
  63.   FILE *cf;
  64.   int ret;
  65.   if (ioctl(cam_fd, VIDIOCGPICT, &cam_pic) < 0) {
  66.     printf("ERROR:VIDIOCGPICT\n");
  67.   }
  68.   /*图像采集格式,网眼V2000只支持VIDEO_PALETTE_YUV420P*/
  69.   cam_pic.palette = VIDEO_PALETTE_YUV420P; //change by 091215


  70. #if 0
  71.     cam_pic.brightness = 30464;
  72.     cam_pic.hue = 36000;
  73.     cam_pic.colour = 0;
  74.     cam_pic.contrast = 43312;
  75.     cam_pic.whiteness = 10312;
  76.     cam_pic.depth = 24;
  77. #endif
  78.     cam_pic.brightness =    30464;
  79.     cam_pic.hue =        111;
  80.     cam_pic.colour =        555;
  81.     cam_pic.contrast =        43312;
  82.     cam_pic.whiteness =        111;
  83.     /*VIDEO_PALETTE_YUV420,bpp=12bit*/
  84.     cam_pic.depth = 12; //bpp == bytes per pixel,change by 091215

  85.     /*设置摄像头缓冲中voideo_picture信息*/
  86.     ret = ioctl( cam_fd, VIDIOCSPICT,&cam_pic );

  87.     if( ret<0 ) {
  88.       close(cam_fd);
  89.       printf("ERROR: VIDIOCSPICT,Can't set video_picture format\n");
  90.     }
  91.     return;
  92. }


  93. void init_video(int w,int h) /* bpp == bytes per pixel*/
  94. {
  95.   int ret;
  96.   
  97.   /*设备的打开*/
  98.   cam_fd = open( USB_VIDEO, O_RDWR );
  99.   if( cam_fd<0 )
  100.     printf("Can't open video device\n");
  101.     /* 使用IOCTL命令VIDIOCGCAP,获取摄像头的基本信息,如最大,最小分辨率*/
  102.   
  103.   ret = ioctl( cam_fd,VIDIOCGCAP,&cam_cap ); /* 摄像头的基本信息*/
  104.   if( ret<0 ) {
  105.     printf("Can't get device information: VIDIOCGCAP\n");
  106.   }
  107.   printf("Device name:%s\nWidth:%d ~ %d\nHeight:%d ~ %d\n",cam_cap.name, cam_cap.maxwidth, cam_cap.minwidth, cam_cap.maxheight, cam_cap.minheight);
  108.   if( ioctl(cam_fd,VIDIOCGWIN,&win)<0 ) {
  109.     printf("ERROR:VIDIOCGWIN\n");
  110.   }
  111.   win.x = 0; //windows中的原点坐标

  112.   win.y = 0; //windows中的原点坐标

  113.   win.width=w; //capture area 宽度

  114.   win.height=h; //capture area 高度

  115.   
  116.   /*使用IOCTL命令VIDIOCSWIN,设置摄像头的基本信息*/
  117.   if (ioctl(cam_fd, VIDIOCSWIN, &win) < 0) {
  118.     printf("ERROR:VIDIOCSWIN\n");
  119.   }
  120.   
  121.   /*设置摄像头voideo_picture信息*/
  122.   config_vid_pic();
  123.   
  124.    /*使用IOCTL命令VIDIOCGCAP,获取获得摄像头存储缓冲区的帧信息*/
  125.   ret = ioctl(cam_fd,VIDIOCGMBUF,&cam_mbuf);
  126.   if( ret<0 ) {
  127.     printf("ERROR:VIDIOCGMBUF,Can't get video_mbuf\n");
  128.   }
  129.   printf("Frames:%d\n",cam_mbuf.frames);
  130.   nframe = cam_mbuf.frames;
  131.   
  132.   /*接着把摄像头对应的设备文件映射到内存区*/
  133.   cam_data = (char*)mmap(0, cam_mbuf.size, PROT_READ|PROT_WRITE,MAP_SHARED,cam_fd,0);
  134.   if( cam_data == MAP_FAILED ) {
  135.     printf("ERROR:mmap\n");
  136.   }
  137.   printf("Buffer size:%d\nOffset:%d\n",cam_mbuf.size,cam_mbuf.offsets[0]);
  138.   InitLookupTable();
  139.   
  140. }


  141. void init_param(T264_param_t* param, const char* file)
  142. {
  143.     int total_no;
  144.     FILE* fd;
  145.     char line[255];
  146.     int32_t b;
  147.     if (!(fd = fopen(file,"r")))
  148.     {
  149.         printf("Couldn't open parameter file %s.\n", file);
  150.         exit(-1);
  151.     }

  152.     memset(param, 0, sizeof(*param));
  153.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  154.     if (b != 4)
  155.     {
  156.         printf("wrong param file version, expect v4.0\n");
  157.         exit(-1);
  158.     }
  159.     fgets(line, 254, fd); sscanf(line,"%d", &param->width);
  160.     fgets(line, 254, fd); sscanf(line,"%d", &param->height);
  161.     fgets(line, 254, fd); sscanf(line,"%d", &param->search_x);
  162.     fgets(line, 254, fd); sscanf(line,"%d", &param->search_y);
  163.     fgets(line, 254, fd); sscanf(line,"%d", &total_no);
  164.     fgets(line, 254, fd); sscanf(line,"%d", &param->iframe);
  165.     fgets(line, 254, fd); sscanf(line,"%d", &param->idrframe);
  166.     fgets(line, 254, fd); sscanf(line,"%d", &param->b_num);
  167.     fgets(line, 254, fd); sscanf(line,"%d", &param->ref_num);
  168.     fgets(line, 254, fd); sscanf(line,"%d", &param->enable_rc);
  169.     fgets(line, 254, fd); sscanf(line,"%d", &param->bitrate);
  170.     fgets(line, 254, fd); sscanf(line,"%f", &param->framerate);
  171.     fgets(line, 254, fd); sscanf(line,"%d", &param->qp);
  172.     fgets(line, 254, fd); sscanf(line,"%d", &param->min_qp);
  173.     fgets(line, 254, fd); sscanf(line,"%d", &param->max_qp);
  174.     fgets(line, 254, fd); sscanf(line,"%d", &param->enable_stat);
  175.     fgets(line, 254, fd); sscanf(line,"%d", &param->disable_filter);
  176.     fgets(line, 254, fd); sscanf(line,"%d", &param->aspect_ratio);
  177.     fgets(line, 254, fd); sscanf(line,"%d", &param->video_format);
  178.     fgets(line, 254, fd); sscanf(line,"%d", &param->luma_coeff_cost);
  179.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  180.     param->flags |= (USE_INTRA16x16) * (!!b);
  181.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  182.     param->flags |= (USE_INTRA4x4) * (!!b);
  183.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  184.     param->flags |= (USE_INTRAININTER) * (!!b);
  185.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  186.     param->flags |= (USE_HALFPEL) * (!!b);
  187.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  188.     param->flags |= (USE_QUARTPEL) * (!!b);
  189.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  190.     param->flags |= (USE_SUBBLOCK) * (!!b);
  191.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  192.     param->flags |= (USE_FULLSEARCH) * (!!b);
  193.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  194.     param->flags |= (USE_DIAMONDSEACH) * (!!b);
  195.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  196.     param->flags |= (USE_FORCEBLOCKSIZE) * (!!b);
  197.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  198.     param->flags |= (USE_FASTINTERPOLATE) * (!!b);
  199.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  200.     param->flags |= (USE_SAD) * b;
  201.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  202.     param->flags |= (USE_EXTRASUBPELSEARCH) * (!!b);
  203.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  204.     param->flags |= (USE_SCENEDETECT) * (!!b);
  205.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  206.     param->block_size |= (SEARCH_16x16P) * (!!b);
  207.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  208.     param->block_size |= (SEARCH_16x8P) * (!!b);
  209.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  210.     param->block_size |= (SEARCH_8x16P) * (!!b);
  211.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  212.     param->block_size |= (SEARCH_8x8P) * (!!b);
  213.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  214.     param->block_size |= (SEARCH_8x4P) * (!!b);
  215.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  216.     param->block_size |= (SEARCH_4x8P) * (!!b);
  217.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  218.     param->block_size |= (SEARCH_4x4P) * (!!b);
  219.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  220.     param->block_size |= (SEARCH_16x16B) * (!!b);
  221.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  222.     param->block_size |= (SEARCH_16x8B) * (!!b);
  223.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  224.     param->block_size |= (SEARCH_8x16B) * (!!b);
  225.     fgets(line, 254, fd); sscanf(line,"%d", &b);
  226.     param->block_size |= (SEARCH_8x8B) * (!!b);
  227.     fgets(line, 254, fd); sscanf(line,"%d", &param->cpu);
  228.     fgets(line, 254, fd); sscanf(line, "%d", &param->cabac);

  229.     //     fgets(line, 254, fd); sscanf(line,"%s", src_path);

  230.     //     fgets(line, 254, fd); sscanf(line,"%s", out_path);

  231.     //     fgets(line, 254, fd); sscanf(line,"%s", rec_path);

  232.     //     param->rec_name = rec_path;


  233.     fclose(fd);
  234. }


  235. void init_encoder()
  236. {
  237.     //编码准备

  238.     const char* paramfile = "fastspeed.txt";
  239.     /*获取fastspeed.txt文件信息*/
  240.     init_param(&m_param, paramfile);
  241.     m_param.direct_flag = 1;
  242.     /*t264编码的打开*/
  243.     m_t264 = T264_open(&m_param);
  244.     m_lDstSize = m_param.height * m_param.width + (m_param.height * m_param.width >> 1);
  245.       /*分配t264解码后数据存放的内存*/
  246.     m_pDst = (uint8_t*)T264_malloc(m_lDstSize, CACHE_SIZE);
  247.     
  248.     /*分配内存用于存放一帧数据长度的数据*/
  249.     m_pPoolData = malloc(m_param.width*m_param.height*3/2);
  250. }
  251.     
  252. void udps_respon(int sockfd,int w,int h)
  253. {
  254.     struct sockaddr_in addrsrc;
  255.     struct sockaddr_in addrdst;
  256.     int addrlen,n;
  257.     
  258.     int32_t iActualLen;
  259.     int row_stride = w*3*h/2;

  260.     bzero(&addrdst,sizeof(struct sockaddr_in));
  261.     addrdst.sin_family=AF_INET;
  262.     /*客户端PC机IP地址*/
  263.     addrdst.sin_addr.s_addr=inet_addr("172.18.23.26");
  264.     addrdst.sin_port=htons(SERVER_PORT);

  265.     while(1)
  266.     {
  267.         /*数据的采集*/
  268.         read_video(NULL,w,h);
  269.         /*对采集到的数据通过H264编码*/
  270.         iActualLen = T264_encode(m_t264, cam_data, m_pDst, row_stride);
  271.         printf("encoded:%d, %d bytes.\n",row_stride,iActualLen);
  272.         /*frame_num:存放帧号*/
  273.         memcpy(m_pPoolData,&m_t264->frame_num,1);
  274.         /*m_pDst解码后的数据*/
  275.         memcpy(m_pPoolData+1, m_pDst, iActualLen);
  276.         iActualLen++;
  277.         /*使用UDP协议发送编码后的数据到客服端*/
  278.         sendto(sockfd,m_pPoolData,iActualLen,0,(struct sockaddr*)&addrdst,sizeof(struct sockaddr_in));     
  279.     }
  280. }


  281. void free_dev()
  282. {
  283.   printf("free device\n");
  284.   close(cam_fd);
  285. }

  286. /*主函数入口*/
  287. int main(void)
  288. {     
  289.     int sockfd;
  290.     struct sockaddr_in addr;

  291.     printf("start 2.0...\n");

  292. /*创建套接字*/
  293.     sockfd=socket(AF_INET,SOCK_DGRAM,0);

  294.     if(sockfd<0)
  295.     {
  296.         printf("0-");
  297.         printf("Socket Error\n");
  298.         exit(1);
  299.     }

  300.     bzero(&addr,sizeof(struct sockaddr_in));
  301.     addr.sin_family=AF_INET;
  302.     addr.sin_addr.s_addr=htonl(INADDR_ANY);
  303.     addr.sin_port=htons(SERVER_PORT);
  304.     /*套接字绑定*/
  305.     if(bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in))<0 )
  306.     {
  307.         printf(stderr,"Bind Error:%s\n",strerror(errno));
  308.         exit(1);
  309.     }

  310.     /*该函数完成编码前的准备*/
  311.     init_encoder();

  312.     atexit( &free_dev );
  313.     /*采集数据前的初始化函数*/
  314.     init_video(m_param.width,m_param.height);

  315.     /*使用UDP协议发送采集到的数据*/
  316.     udps_respon(sockfd,m_param.width,m_param.height);
  317.     
  318.     close(sockfd);

  319. }
阅读(2810) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~