织梦CMS - 轻松建站从此开始!

罗索

linux下视频采集服务器(UDP传输、多线程模式)

jackyhwei 发布于 2010-01-26 09:47 点击:次 
linux下多线程网络编程,实现arm9视频采集和网络发送jpeg数据,使用udp协议,自己写的,搞了好几天!linux下的多线程比较复杂易出错。
TAG:

linux下多线程网络编程,实现arm9视频采集和网络发送jpeg数据,使用udp协议,自己写的,搞了好几天!linux下的多线程比较复杂易出错。

linux network under the multi-threaded programming, video capture and realize ARM9 send jpeg data network, using udp protocol, wrote it myself, engaged in for several days! linux under the more complicated multi-threaded, error-prone.

  1. //多线程成功实例  
  2.  
  3. #include <strings.h>  
  4. #include <stdio.h>  
  5. #include <unistd.h>  
  6. #include <stdlib.h>  
  7. #include <errno.h>  
  8. #include <stdarg.h>  
  9. #include <linux/types.h>   
  10. #include <linux/videodev.h>  
  11. #include <pthread.h>  
  12. #include <semaphore.h>  
  13. #include <sys/types.h>  
  14. #include <sys/mman.h>  
  15. #include <sys/ioctl.h>  
  16. #include <sys/stat.h>  
  17. #include <sys/time.h>  
  18. #include <sys/file.h>  
  19. #include <sys/stat.h>  
  20. #include <fcntl.h>  
  21. #include <time.h>  
  22. #include <string.h>   
  23. #include <netdb.h>  
  24. #include <arpa/inet.h>  
  25. #include <sys/times.h>  
  26. #include <netinet/in.h>  
  27. #include <sys/socket.h>  
  28. #include <sys/param.h>  
  29. #include <ctype.h>  
  30. #include <sys/utsname.h>  
  31.  
  32. #define BUFSIZE  6  
  33. #define DATA     32*1024  
  34. #define PORT     5000   
  35. #define RTP_HDR_SZ 12   
  36. #define VIDEO_PALETTE_JPEG 21   
  37.     
  38. unsigned char buf[BUFSIZE+2][DATA];   
  39. int head,tail;   
  40.    
  41. sem_t writen;   
  42. sem_t readn;  
  43.  
  44. struct ARG{int sockfd;  
  45.  int sin_size;  
  46.  struct sockaddr_in client;   
  47. };  
  48.    
  49. struct FDG{   
  50. int video_fd;   
  51. };  
  52.    
  53. typedef unsigned char  u_int8;   
  54. typedef unsigned short u_int16;   
  55.  
  56. int get_jpegsize (unsigned char *buf, int insize);  
  57. double tdbl(struct timeval *a);   
  58. pthread_mutex_t  buffer_mutex=PTHREAD_MUTEX_INITIALIZER;   
  59.    
  60. static void *producer(void *fdg)   
  61. {  
  62.   struct FDG *vd;   
  63.  int video_fd;  
  64.    
  65.   if(sizeof(fdg)!=sizeof(struct FDG))  
  66.   {  
  67.     perror("producer arg error");  
  68.     exit(1);  
  69.    }  
  70.   else   
  71.   {   
  72.   vd=(struct FDG *)fdg;   
  73.   video_fd=vd->video_fd;   
  74.   free(fdg);  
  75.   fdg=NULL;  
  76.   }  
  77.  
  78.      
  79.   for( ; ; )  
  80.   {   
  81.          sem_wait(&writen);//减少可读的资源数   
  82.          pthread_mutex_lock(&buffer_mutex);//进入互斥区  
  83.        // memset(buf[head], 's', 20);   
  84.          read(video_fd, buf[head], DATA);   
  85.          head=(head+1) % BUFSIZE;   
  86.           
  87.          pthread_mutex_unlock(&buffer_mutex);//离开互斥区   
  88.          sem_post(&readn);//增加可读资源数   
  89.         // sleep(0.0001);   
  90.   }  
  91. }  
  92.  
  93.    
  94. static void *consumer(void *arg)   
  95. {   
  96.   int sockfd;  
  97.   int sin_size;  
  98.   int jpegsize;  
  99.   struct sockaddr_in client;  
  100.   struct ARG *info;  
  101.     
  102.   typedef struct {   
  103.     unsigned int version:2;/* protocol version */   
  104.     unsigned int p:1;     /* padding flag */   
  105.     unsigned int x:1;     /* header extension flag */   
  106.     unsigned int cc:4;    /* CSRC count */   
  107.     unsigned int m:1;     /* marker bit */   
  108.     unsigned int pt:7;    /* payload type */   
  109.     unsigned int seq:16;  /* sequence number */   
  110.     unsigned int ts;      /* timestamp */   
  111.     unsigned int ssrc;    /* synchronization source */   
  112.   } rtp_hdr_t;  
  113.    
  114.   struct timeval start;   
  115.     
  116.   rtp_hdr_t rtphdr;  
  117.   u_int8 *jpeg_data;   
  118.   u_int8 *packet_buf;  
  119.   unsigned int  ts;  
  120.   unsigned int ssrc;  
  121.   u_int8 *ptr;  
  122.   u_int8 frame,bframe;  
  123.   int bytes_left ;//jpeg数据总长度  
  124.   int data_len,packetsize;//packetsize变量  
  125.    
  126.   info=( struct ARG *)arg;  
  127.   if(info->sockfd<0)  
  128.   {   
  129.     perror("error error");  
  130.     exit(1);  
  131.   }  
  132.     
  133.   if(info->sin_size!=16)  
  134.   {   
  135.     perror("err error");  
  136.     exit(1);  
  137.   }  
  138.   sockfd=info->sockfd;  
  139.   sin_size=info->sin_size;  
  140.   memcpy(&client,&info->client,sizeof(info->client));  
  141.   free(arg);   
  142.   arg=NULL;  
  143.     
  144.   packetsize=RTP_HDR_SZ+2050;  
  145.   packet_buf = (u_int8 *)calloc(packetsize, sizeof(u_int8));  
  146.   jpeg_data= (u_int8 *) malloc(DATA);   
  147.    
  148.   for(;;)  
  149.   {  
  150.     frame=0;   
  151.     gettimeofday(&start, 0);  
  152.     ts = (unsigned int)(tdbl(&start)*1000);  
  153.     ssrc = 125;  
  154.     /* Initialize RTP header*/ 
  155.      
  156.     rtphdr.version = 2;  
  157.     rtphdr.p = 0;  
  158.     rtphdr.x = 0;  
  159.     rtphdr.cc = 0;  
  160.     rtphdr.m = 0;  
  161.     rtphdr.pt = 40;  
  162.     rtphdr.seq = 1;  
  163.     rtphdr.ts = htonl(ts);  
  164.     rtphdr.ssrc = htonl(ssrc);  
  165.    
  166.          sem_wait(&readn);//减少可读的资源数  
  167.             
  168.          pthread_mutex_lock(&buffer_mutex);//进入互斥区  
  169.            
  170.          jpegsize=get_jpegsize(buf[tail],DATA);  
  171.            
  172.          if(jpegsize!=-1)  
  173.           {   
  174.             memcpy(jpeg_data,buf[tail],jpegsize);   
  175.           }   
  176.           
  177.          tail=(tail+1) % BUFSIZE;  
  178.          
  179.          pthread_mutex_unlock(&buffer_mutex);//离开互斥区  
  180.           
  181.          sem_post(&writen);//增加可读资源数  
  182.     
  183.    bytes_left = jpegsize;         
  184.     
  185.   while (bytes_left > 0)    
  186.   {  
  187.     ptr = packet_buf + RTP_HDR_SZ;  
  188.      
  189.     bframe=frame;  
  190.     
  191.     data_len = packetsize - (ptr - packet_buf)-2;//每一分片大小  
  192.  
  193.     if (data_len >= bytes_left)   //当为最后一个分片时  
  194.     {  
  195.       data_len = bytes_left;  
  196.       rtphdr.m = 1;  
  197.       bframe=255;  
  198.       data_len=jpegsize%2048;  
  199.     }  
  200.       
  201.    *ptr=bframe;  ptr++;  
  202.    *ptr=frame;   ptr++;  
  203.      
  204.     rtphdr.seq = htons(rtphdr.seq);  
  205.     memcpy(packet_buf, &rtphdr, RTP_HDR_SZ);  
  206.     memcpy(ptr, jpeg_data + frame*2048, data_len);  
  207.      
  208.     if(sendto(sockfd,packet_buf,(ptr - packet_buf) + data_len,
  209. 0,(struct sockaddr *)&client,sin_size)<0)  
  210.      {  
  211.        perror(" sendto error");    
  212.      }  
  213.        
  214.     frame++;  
  215.     bytes_left -= 2048;  
  216.     rtphdr.seq = ntohs(rtphdr.seq);  
  217.     rtphdr.seq++;  
  218.   }  
  219.           
  220.        sleep(0.0001);       
  221.   }  
  222.   free(packet_buf);  
  223.   free(jpeg_data);  
  224.   pthread_exit(NULL);  
  225. }  
  226.  
  227.    
  228. int main()   
  229. {   
  230.   clock_t oldtick,newtick;  
  231.   float time1 ;  
  232.   static int vf=0;  
  233.   int i;  
  234.   clock_t totalold,totalnew;  
  235.   int video_fd;  
  236.   struct video_capability grab_cap;  
  237.  
  238.   int width = 320;  
  239.   int height = 240;  
  240.  
  241.  
  242.   struct video_picture grab_pic;  
  243.   struct video_mmap grab_map;  
  244.   struct video_mbuf grab_buf;  
  245.    
  246.    
  247.   int sockfd;  
  248.   int sin_size;  
  249.   struct sockaddr_in client;   
  250.   struct sockaddr_in server;  
  251.   char msg[100];  
  252.   struct ARG *arg;   
  253.   struct FDG  *fdg;   
  254.   pthread_t p_tid;   
  255.   pthread_t c_tid;  
  256.   head=0;  
  257.   tail=0;  
  258.   for(i=0; i<BUFSIZE+2; i++)  
  259.   {   
  260.     bzero(buf[i],DATA);  
  261.      
  262.    }  
  263.   sem_init(&writen,0,BUFSIZE);   
  264.   sem_init(&readn,0,0);   
  265.    
  266. //数据采集………………………………………………  
  267. loop:  
  268.  totalold = clock();  
  269.  video_fd = open("/dev/video0", O_RDWR);  
  270.  if (video_fd == -1)   
  271.  {
  272. //\u6253\u5f00\u6444\u50cf\u5934
  273.    fprintf(stderr, "can not open video0");
  274.    exit(1);
  275.  }
  276.  oldtick = clock();
  277.  if ((ioctl(video_fd, VIDIOCGCAP, &grab_cap)) < 0)
  278.  {
  279.    fprintf(stderr, "ioctl VIDEOCGCAP failed.");
  280.    exit(1);
  281.  }
  282.  newtick = clock();
  283.  time1 = (double)(newtick - oldtick)/ CLOCKS_PER_SEC;
  284.  printf("\n%f second is take to ioctl VIDEOCGCAP \n",time1);
  285.  
  286. printf("The VideoCap Name: %s\n", grab_cap.name);
  287. printf("The hannels: %d\n", grab_cap.channels);
  288. printf("The Audios: %d\n", grab_cap.audios);
  289. printf("The maxwidth: %d, maxheight: %d, minwidth %d, minheight: %d\n",
  290. grab_cap.maxwidth, grab_cap.maxheight,
  291. grab_cap.minwidth, grab_cap.minheight);  
  292.  
  293.  oldtick = clock();  
  294.  
  295. if ((ioctl(video_fd, VIDIOCGPICT, &grab_pic)) < 0)   
  296. {  
  297.   fprintf(stderr, "ioctl VIDIOCGPICT failed.");  
  298.   exit(1);  
  299. }  
  300.  newtick = clock();  
  301.  time1 = (double)(newtick - oldtick)/ CLOCKS_PER_SEC;  
  302.  printf("\n%f second is take to ioctl VIDIOCGPICT \n",time1);  
  303.  
  304. printf("The brightness: %d\nThe hue: %d\nThe colour: %d\n
  305. The contrast:%d\nThe whiteness: %d\nThe depth: %d\nThe palette: %d\n",
  306. grab_pic.brightness, grab_pic.hue, grab_pic.colour, grab_pic.contrast,
  307. grab_pic.whiteness, grab_pic.depth, grab_pic.palette);  
  308.  
  309.  oldtick = clock();  
  310.  
  311. if ((ioctl(video_fd, VIDIOCGMBUF, &grab_buf)) < 0)   
  312. {  
  313.   fprintf(stderr, "ioctl VIDIOCGMBUF, failed.");  
  314.   exit(1);  
  315. }  
  316.  newtick = clock();  
  317.  time1 = (double)(newtick - oldtick)/ CLOCKS_PER_SEC;  
  318.  printf("\n%f second is take to ioctl VIDIOCGMBUF \n",time1);  
  319.  
  320. printf("The mapping size:%d\nThe mapping frames:%d\nThe mapping offset %d\n",
  321. grab_buf.size, grab_buf.frames, grab_buf.offsets);  
  322. printf("The mapping size: %d  nihao\n",grab_buf.size);  
  323. grab_map.width = width;  
  324. grab_map.height = height;  
  325. grab_map.format = VIDEO_PALETTE_JPEG;  
  326. grab_map.frame = 0;  
  327. if(vf==0)  
  328. {  
  329.   vf=vf+1;  
  330.   close(video_fd);  
  331.   goto loop;  
  332. }  
  333.  
  334.    
  335. fdg=(struct FDG *)malloc(sizeof(struct FDG));  
  336. if(fdg==NULL)  
  337. {   
  338.   perror("fdg malloc error");  
  339.   exit(1);  
  340.  }  
  341.  else  {fdg->video_fd=video_fd;}   
  342.    
  343. if(pthread_create(&p_tid, NULL, producer, (void *)fdg))  
  344. {  
  345.    perror("pthrea p_tid1 error!");  
  346.    exit(1);  
  347. }  
  348.    
  349.   // free(fdg);  
  350.   // fdg=NULL;  
  351.  
  352. //网络部分  
  353. if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)  
  354. {  
  355. perror("creat socket error");  
  356. exit(1);  
  357. }  
  358.  
  359. bzero(&server,sizeof(server));  
  360. server.sin_family=AF_INET;  
  361. server.sin_port=htons(PORT);  
  362. server.sin_addr.s_addr=htonl(INADDR_ANY);  
  363. if(bind(sockfd,(struct sockaddr *)&server,sizeof(struct sockaddr))==-1){  
  364. perror("bind error");  
  365. exit(1);}  
  366.  
  367. sin_size=sizeof(struct sockaddr_in);  
  368.         
  369.   while(1)  
  370.   {  
  371.       
  372.     if((recvfrom(sockfd,msg,100,0,(struct sockaddr *)&client,&sin_size))<0)  
  373.     {  
  374.          perror("recv error");  
  375.           exit(1);  
  376.      }  
  377.        
  378.    arg=(struct ARG *)malloc(sizeof(struct ARG));  
  379.   if(arg==NULL)  
  380.   {  
  381.     perror("ARG malloc error");  
  382.     exit(1);  
  383.    }  
  384.   else {  
  385.          arg->sockfd=sockfd;  
  386.          arg->sin_size=sin_size;  
  387.          memcpy((void *)&arg->client,&client,sizeof(client));  
  388.         }  
  389.    
  390.      
  391.  if(pthread_create(&c_tid,NULL,consumer,(void *)arg))  
  392.  {  
  393.   perror("pthread c_tid error!");  
  394.    exit(1);  
  395.  }  
  396.    
  397.  // free(arg);  
  398.   // arg=NULL;   
  399.     
  400.   }  
  401.      
  402. pthread_join(p_tid,NULL);  
  403. //pthread_join(p_tid2,NULL);   
  404. pthread_join(c_tid,NULL);   
  405. close(video_fd);  
  406. close(sockfd);  
  407. return 0;  
  408.  
  409. }   
  410.       
  411.    //获得JPEG图片大小  
  412. int get_jpegsize (unsigned char *buf, int insize)  
  413. {  
  414.  int i,flg=0,fc=0,fd=0,nd=0,k;   
  415.     
  416.   if((buf[0]==0xFF) && (buf[1]==0xD8)&& (buf[2]==0xFF) && (buf[3]==0xDB))   
  417.   {      
  418.         for ( k= 0 ; k< 590; k++)   
  419.         {   
  420.           if(buf[k]== 0x0D)nd++;  
  421.             
  422.           if ((buf[k]== 0xFF) && (buf[k+1] == 0xC4))   
  423.           {  
  424.                flg++;  
  425.                fc=k+1;  
  426.            }  
  427.           if ((buf[k]== 0xFF) && (buf[k+1] == 0xDA))   
  428.           {  
  429.                fd=k+1;  
  430.                flg++;  
  431.                break;  
  432.            }  
  433.                
  434.          }  
  435.        
  436.    if((flg==2)&&(fc==137)&&(fd==576)&&(nd<=5))  
  437.    {  
  438.             
  439.      for ( i= 1024*2 ; i< insize; i++)  
  440.       {  
  441.         if ((buf[i] == 0xFF) && (buf[i+1] == 0xD9)) return i+2;  
  442.       }   
  443.       
  444.    }   
  445.   }  
  446.  return -1;  
  447. }  
  448.  
  449.  
  450.  
  451. double tdbl(struct timeval *a)  
  452. {  
  453.   return a->tv_sec + a->tv_usec/1e6;  
  454. }  

 

(sun)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201001/8381.html]
本文出处:网络博客 作者:sun
顶一下
(11)
91.7%
踩一下
(1)
8.3%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容