LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 11224|回复: 47

大家一起来讨论video for linux的编程。

[复制链接]
发表于 2004-6-14 13:17:37 | 显示全部楼层 |阅读模式
大家看下我写的实现streamio方式捕获视频桢的程序。
大家互相交流下经验。
有没有谁做过overlay和capture同时进行的程序呀?
希望可以抛砖引玉。

  1. #include <stdio.h>
  2. #include <errno.h>
  3. #include <sys/ioctl.h>
  4. #include <sys/stat.h>
  5. #include <fcntl.h>
  6. #include <linux/types.h>
  7. #include <unistd.h>
  8. #include <stdlib.h>
  9. #include <sys/mman.h>
  10. #include <sys/poll.h>

  11. #include <linux/videodev.h>

  12. #define FILENAME "/dev/video"

  13. #define IOCTL(fd, req, addr )   ((-1==ioctl(fd,req,addr))?(perror(#req),exit(EXIT_FAILURE)):0)

  14. int main(void) {
  15.      int fd;
  16.      struct  v4l2_capability cap;
  17.      v4l2_std_id std;
  18.      struct v4l2_format format;
  19.      struct v4l2_requestbuffers reqbuf;
  20.      struct {
  21.              void * start;
  22.              size_t length;
  23.      } * buffers;
  24.      struct v4l2_buffer buffer;
  25.      unsigned int i,x,y,index;
  26.      unsigned char *data,*ptr;
  27.      FILE *pgm ;
  28.         //open device file
  29.         fd = open(FILENAME,O_RDWR);
  30.         //query the device's ability
  31.         IOCTL(fd, VIDIOC_QUERYCAP, &cap);
  32.          //if device can support capture and streamio
  33.          if ( (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)&&(cap.capabilities & V4L2_CAP_STREAMING)) {
  34.              //set the current input is composite 1
  35.              index = 1;
  36.              IOCTL(fd,VIDIOC_S_INPUT,&index);
  37.              //query the current video std whether PAL
  38.              IOCTL(fd,VIDIOC_G_STD,&std);
  39.              //if the current video std is PAL
  40.                 if ( std & V4L2_STD_PAL)   {
  41.                   //negotiate the image format
  42.                   format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  43.                   IOCTL(fd,VIDIOC_G_FMT,&format);
  44.                   //printf("the current pixelformat is %x \n",format.fmt.pix.pixelformat);
  45.                   format.fmt.pix.width = 384;
  46.                   format.fmt.pix.height = 288;
  47.                   format.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
  48.                   format.fmt.pix.field = V4L2_FIELD_TOP;
  49.                   format.fmt.pix.bytesperline = 384*3;
  50.                   format.fmt.pix.sizeimage = 384*288*3;
  51.                   format.fmt.pix.colorspace =V4L2_COLORSPACE_SRGB;//SMPTE170M;
  52.                   format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  53.                   IOCTL(fd,VIDIOC_S_FMT,&format);
  54.                   printf("change the  current pixelformat is %c%c%c%c\n",(format.fmt.pix.pixelformat & 0x000000FF) ,((format.fmt.pix.pixelformat & 0x0000FF00)>>8),
  55.                                                     ((format.fmt.pix.pixelformat & 0x00FF0000)>>16), ((format.fmt.pix.pixelformat & 0xFF000000)>>24) );
  56.                   // negotiate the request buffer
  57.                   reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  58.                   reqbuf.memory = V4L2_MEMORY_MMAP;
  59.                   reqbuf.count = 2;
  60.                   //init the device memory
  61.                   IOCTL(fd,VIDIOC_REQBUFS,&reqbuf );
  62.                      //if init fails
  63.                     if (reqbuf.count < 2) {
  64.                         printf ("Not enough buffer memory\n");
  65.                         exit (EXIT_FAILURE);
  66.                     }
  67.                   buffers = calloc (reqbuf.count,sizeof(*buffers));//later clean the buffers can use
  68.                  // assert(buffers != NULL);
  69.                     //map the device memory to application memory
  70.                      for (i=0;i<reqbuf.count;i++) {

  71.                         buffer.type = reqbuf.type;
  72.                         buffer.index =i ;
  73.                         //query the status of one buffer
  74.                         IOCTL(fd,VIDIOC_QUERYBUF,&buffer);
  75.                         buffers[i].length = buffer.length;
  76.                         buffers[i].start = mmap (NULL,buffer.length,
  77.                                                PROT_READ | PROT_WRITE,
  78.                                                MAP_SHARED,
  79.                                                fd,buffer.m.offset);
  80.                          if (buffers[i].start == MAP_FAILED) {
  81.                              perror ("mmap");
  82.                              exit(EXIT_FAILURE);
  83.                           }
  84.                      }


  85.                //begian streaming
  86.                 IOCTL(fd,VIDIOC_STREAMON,&reqbuf.type);
  87.                //put one frame into the device incoming queue
  88.                 buffer.type = reqbuf.type;
  89.                 buffer.index = 0;
  90.                // IOCTL( fd, VIDIOC_QUERYBUF, &buffer );
  91.                //put another frame into the device incoming queue
  92.                 IOCTL(fd,VIDIOC_QBUF,&buffer);
  93.                 buffer.type =reqbuf.type;
  94.                 buffer.index =1 ;
  95.                // IOCTL(fd,VIDIOC_QUERYBUF,&buffer);
  96.                 IOCTL(fd,VIDIOC_QBUF,&buffer);


  97.                //get one frame out of the incoming queue and save as a pgm file
  98.                 buffer.type = reqbuf.type;
  99.                 buffer.index = 0;
  100.                 IOCTL( fd, VIDIOC_DQBUF, &buffer );
  101.                  data = buffers[0].start;
  102.                  pgm = fopen( "framea.pgm", "w" );
  103.                  fprintf( pgm, "P2\n%d %d 255\n",
  104.                       format.fmt.pix.width, format.fmt.pix.height );
  105.                  ptr = data;
  106.                  for( y = 0; y < format.fmt.pix.height; y++ ) {
  107.                  for( x = 0; x < format.fmt.pix.width; x++ ) {
  108.                   fprintf( pgm, "%03d ",
  109.                                     (ptr[ 0] + ptr[1] + ptr[2] ) / 3 );
  110.                   ptr += 3;
  111.                     }
  112.                   fprintf( pgm, "\n" );
  113.                  }
  114.                 fclose( pgm );
  115.                 //get another frame out of the incoming queue and save as a pgm file
  116.                 buffer.type = reqbuf.type;
  117.                 buffer.index = 1;
  118.                 IOCTL( fd, VIDIOC_DQBUF, &buffer );
  119.                  data = buffers[1].start;
  120.                  pgm = fopen( "frameb.pgm", "w" );
  121.                  fprintf( pgm, "P2\n%d %d 255\n",
  122.                       format.fmt.pix.width, format.fmt.pix.height );
  123.                  ptr = data;
  124.                  for( y = 0; y < format.fmt.pix.height; y++ ) {
  125.                  for( x = 0; x < format.fmt.pix.width; x++ ) {
  126.                   fprintf( pgm, "%03d ",
  127.                                     (ptr[ 0] + ptr[1] + ptr[2] ) / 3 );
  128.                   ptr += 3;
  129.                     }
  130.                   fprintf( pgm, "\n" );
  131.                   }
  132.                  fclose( pgm );
  133.                 //stop the stream
  134.                 IOCTL( fd, VIDIOC_STREAMOFF, &reqbuf.type );
  135.                 //clean the allocated buffers
  136.                  for (i=0;i<reqbuf.count;i++)
  137.                         munmap (buffers[i].start,buffers[i].length);
  138.                //close the device file and return
  139.                close(fd);
  140.                return 0;
  141.                }
  142.          }
  143. }
复制代码
发表于 2004-6-14 20:58:11 | 显示全部楼层
楼主有无跨网关传输多通道视频流方面的方案?
 楼主| 发表于 2004-6-15 09:44:56 | 显示全部楼层
暂时还没有,目前下一步的打算是把视频压缩算法集成到我程序中。
 楼主| 发表于 2004-6-15 09:52:33 | 显示全部楼层
不过,为了准备到intervideo公司的第二轮面试,计划可能要往后推了。
我作完以后授权将是gpl,方便大家一起研究。
发表于 2004-6-15 21:41:42 | 显示全部楼层
无奈对c语言一知半解,,,,
兄弟可以参阅gaim-vv(gaim voice video,gaim视频版,不知道现在怎么样了,sourceforge.net)项目代码。。。
现在写java,c语言看不进去了。。。
发表于 2004-6-17 10:11:47 | 显示全部楼层
overlay和capture同时进行的程序
1.format.fmt.pix.pixelformat = yuv format
2.create new thread for QBuf and DQBuf, after received a full image, tranfer it to main funtion for display it.
 楼主| 发表于 2004-6-17 17:26:25 | 显示全部楼层
如果你的framebuffer只支持8、16、24、32 rgb颜色格式,overlay如果用yuyv或yvyu,好象不能正常显示了呀。
楼上的有什么说法?
 楼主| 发表于 2004-6-17 17:28:27 | 显示全部楼层
另外按你的方式,另建队列获取视频桢之后,怎样再放到framebuffer上显示呢?
请问你用的什么方法?sdl或者directfb??
发表于 2004-6-17 18:59:06 | 显示全部楼层
我使用的是SDL.
screen = SDL_SetVideoMode(w,h,16,SDL_SWSURFACE);
overlay = SDL_CreateYUVOverlay(w,h,SDL_YUY2_OVERLAY,screen);
获取视频桢之后,
SDL_LockYUVOverlay(overlay);
memcpy(overlay->pixels[0], image, size);
SDL_UnlockYUVOvelay(overlay);
SDL_DisplayYUVOverlay(overlay,&rect);
 楼主| 发表于 2004-6-18 09:29:59 | 显示全部楼层
楼上的还真是高手呀,你是作多媒体的吗?以后还请多指教。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表