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

罗索

v4l videocap

落鹤生 发布于 2012-05-03 11:09 点击:次 
落鹤生:完整的V4L视频采集代码,包括取得摄像头列表,打开摄像头,设置视频采集参数,采集视频等等。跟大家分享。
TAG:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <malloc.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <pthread.h>

#include <linux/videodev2.h>
#include <libv4l2.h>

#include "sowebcam-linux.h"

#define VIDIOC_G_FRAMERATE      _IOWR('V', 200, int)
#define VIDIOC_S_FRAMERATE      _IOWR('V', 201, int)
#define VIDIOC_G_COMPQUALITY  _IOWR('V', 202, int)
#define VIDIOC_S_COMPQUALITY  _IOWR('V', 203, int)

#define INIT_ID   0xFE567DA0

typedef struct tagSoV4l2Buffer
{
 void*   start;
 size_t  length;
}SoV4l2Buffer;

static struct SoVCData
{
 unsigned int  init_id;
 SOLCAM_STATUS   status;
 int    stopped;
 
 int    h264_fd;
 
 SoV4l2Buffer*   h264_buffers;
 unsigned int    h264_buffer_num;
 
 FN_CAPTURE_CALLBACK fn_capture;
 FN_ERROR_CALLBACK fn_error;
 
 double    cur_framerate;
 int    cur_bitrate; 
}sovc_data;

const char *sp_h264_dev = "/dev/v4l/by-id/usb-Ningbo_Sunny_Opotech_Co._Ltd_Sunny_HD_WebCam_UVC_UAC__1.0.1-video-index0";
      
static int is_file_exist(const char* file_name)
{
    struct stat namestat;

    if(file_name == NULL || strlen(file_name) == 0)
        return 0;

    if(stat(file_name, &namestat) == -1)
        return 0;
    return 1;
}

static int xioctl(int fd, int request,void *arg)
{
    int r;

    do r = ioctl (fd, request, arg);
    while (-1 == r && EINTR == errno);

    return r;
}

SOERR solcam_vc_init()
{
 if(sovc_data.init_id == INIT_ID)
  return SOERR_NONE;
  
 if(!is_file_exist(sp_h264_dev))
 {
  printf("the sunny-webcam device is not been pluged\n");
  return SOERR_NO_CAM_DEVICE;
 }
 
 memset(&sovc_data, 0, sizeof(sovc_data));
 
 sovc_data.status = SOLCAM_STATUS_STOPPED;
 sovc_data.init_id = INIT_ID;
 
    return SOERR_NONE;
}

static long get_tick_count()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (tv.tv_sec * 1000 + tv.tv_usec/1000);
}

static void test_fps_bitrate(int frame_size)
{
    static int frames_num =0;
    static long start_time = 1;
    static long total_frame_size = 0;
    if(start_time == 1)
    {
        start_time = get_tick_count();
    }
    frames_num++;
    total_frame_size += frame_size;
    if(frames_num%30 == 0)
    {
        sovc_data.cur_framerate = (double)frames_num*1000/(get_tick_count()-start_time);
        sovc_data.cur_bitrate = (int)(total_frame_size*1000/(get_tick_count()-start_time));
        start_time = get_tick_count();
        frames_num = 0;
        total_frame_size = 0;
    }
}

static void* video_capture_thread(void* param)
{
    struct v4l2_buffer buf;
    enum v4l2_buf_type type;
    int i = 0;
   
    param = param;
    sovc_data.status = SOLCAM_STATUS_RUNNING;
    sovc_data.stopped = 0;
   // printf("enter video capture thread\n");
    while(sovc_data.status == SOLCAM_STATUS_RUNNING)
    {
  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  buf.memory = V4L2_MEMORY_MMAP;
        //printf("capture one frame-2\n");
  if (-1 == xioctl (sovc_data.h264_fd, VIDIOC_DQBUF, &buf))
  {
   if(sovc_data.fn_error)
    sovc_data.fn_error("failed dqbuf\n");
   break;
  }
        //printf("capture one frame-1\n");
  if(sovc_data.fn_capture)
  {
   sovc_data.fn_capture(sovc_data.h264_buffers[buf.index].start, buf.bytesused);
   test_fps_bitrate(buf.bytesused);
          //  printf("capture one frame\n");
  }

  if (-1 == xioctl (sovc_data.h264_fd, VIDIOC_QBUF, &buf))
  {
   if(sovc_data.fn_error)
    sovc_data.fn_error("failed qbuf\n");
   break;
  }
 }
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    //printf("exit video capture thread\n");
 if (-1 == xioctl (sovc_data.h264_fd, VIDIOC_STREAMOFF, &type))
 {
        printf("VIDIOC_STREAMOFF failed\n");
 }
 sovc_data.status = SOLCAM_STATUS_STOPPED;
 for (i = 0; i < sovc_data.h264_buffer_num; ++i)
 {
  munmap (sovc_data.h264_buffers[i].start, sovc_data.h264_buffers[i].length);
 }
 free(sovc_data.h264_buffers);
 sovc_data.stopped = 1;
    //printf("exit video capture thread-1\n");
 return NULL;
}

#ifndef V4L2_PIX_FMT_H264
#define V4L2_PIX_FMT_H264  v4l2_fourcc('H', '2', '6', '4') /*  H264 stream     */
#endif

static SOERR vc_set_res(VideoRes* video_res)
{
    struct v4l2_format fmt;
 
 if(video_res == NULL)
 {
  return SOERR_INVALID_PARAM;
 }
 
 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED;
 
 if(sovc_data.status == SOLCAM_STATUS_RUNNING)
 {
  return SOERR_WRONG_STATUS;
 }
 
 memset(&fmt, 0, sizeof(struct v4l2_format));
 
    fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width       = video_res->width;
    fmt.fmt.pix.height      = video_res->height;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
    fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;

    if (-1 == xioctl (sovc_data.h264_fd, VIDIOC_S_FMT, &fmt))
    {
     printf("failed set yo resolution\n");
  return SOERR_FAILED_SET_RES;
    }
    return SOERR_NONE;
}

static SOERR vc_set_framerate(int framerate)
{
 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED;
 
 if (v4l2_ioctl (sovc_data.h264_fd, VIDIOC_S_FRAMERATE, &framerate) < 0)
 {
  printf("get brightness failed!\n");
  return SOERR_FAILED_SET_FRAMERATE;
 }
 return SOERR_NONE;
}


SOERR solcam_vc_run(VideoRes *res, int fps, FN_CAPTURE_CALLBACK fn_capture, FN_ERROR_CALLBACK fn_error)
{
 enum  v4l2_buf_type   type;
 struct v4l2_capability   cap;
 struct v4l2_requestbuffers  req;
 int i = 0;
 SOERR ret = SOERR_FAILED_START_VIDEO_CAP;
 
 if(!is_file_exist(sp_h264_dev))
 {
  printf("the sunny-webcam device is not been pluged\n");
  return SOERR_NO_CAM_DEVICE;
 }
 
 if(res == NULL)
  return SOERR_INVALID_PARAM;

 if(fps!=10 && fps!=15 && fps!=20 && fps!=25 && fps!=30)
  return SOERR_INVALID_PARAM;

    sovc_data.h264_fd = open(sp_h264_dev, O_RDWR);
 if(sovc_data.h264_fd <= 0)
 {
  printf("sunny webcam device can not be opened!\n");
  goto error;
 }
 
 ret = vc_set_res(res);
 if(ret != SOERR_NONE)
 {
  goto error;
 }
 
 ret = vc_set_framerate(fps);
 if(ret != SOERR_NONE)
 {
  goto error;
 }
 
 if (-1 == xioctl (sovc_data.h264_fd, VIDIOC_QUERYCAP, &cap))
 {
  printf("ioctl VIDIOC_QUERYCAP failed\n");
  goto error;
 }
 
    if(!((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && (cap.capabilities & V4L2_CAP_STREAMING)))
    {
        printf ("no video capture device\n");
        goto error;
    }

    memset(&req, 0, sizeof(struct v4l2_requestbuffers));
 req.count               = 4;
 req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 req.memory              = V4L2_MEMORY_MMAP;

 if (-1 == xioctl (sovc_data.h264_fd, VIDIOC_REQBUFS, &req))
 {
  if(EINVAL == errno)
  {
    printf("does not support memory mapping\n");
  }
  printf("VIDIOC_REQBUFS\n");
  goto error;
    }

    if (req.count < 2)
    {
        printf("Insufficient buffer memory\n");
        goto error;
    }
 sovc_data.h264_buffer_num = req.count;
    sovc_data.h264_buffers = (SoV4l2Buffer*)calloc (sovc_data.h264_buffer_num, sizeof(SoV4l2Buffer));
 
    if (!sovc_data.h264_buffers)
    {
        printf("Out of memory\n");
        goto error;
    }

    for (i = 0; i < sovc_data.h264_buffer_num; ++i)
    {
        struct v4l2_buffer buf;

        memset(&buf, 0, sizeof(struct v4l2_buffer));

        buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory      = V4L2_MEMORY_MMAP;
        buf.index       = i;

        if (-1 == xioctl (sovc_data.h264_fd, VIDIOC_QUERYBUF, &buf))
        {
            printf("VIDIOC_QUERYBUF\n");
            goto error;
  }
  
        sovc_data.h264_buffers[i].length = buf.length;
        sovc_data.h264_buffers[i].start = mmap (NULL /* start anywhere */,
            buf.length,
            PROT_READ | PROT_WRITE /* required */,
            MAP_SHARED /* recommended */,
            sovc_data.h264_fd, buf.m.offset);

        if (MAP_FAILED == sovc_data.h264_buffers[i].start)
        {
         sovc_data.h264_buffers[i].length = 0;
            printf("mmap failed\n");
   goto error;
        }
    }
   
 for (i = 0; i < sovc_data.h264_buffer_num; ++i)
 {
  struct v4l2_buffer buf;

  memset(&buf, 0, sizeof(struct v4l2_buffer));

  buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  buf.memory      = V4L2_MEMORY_MMAP;
  buf.index       = i;

  if (-1 == xioctl (sovc_data.h264_fd, VIDIOC_QBUF, &buf))
  {
   printf("VIDIOC_QBUF failed\n");
   goto error;
  }
 }
  
 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 if (-1 == xioctl (sovc_data.h264_fd, VIDIOC_STREAMON, &type))
 {
  printf("VIDIOC_STREAMON failed\n");
  goto error;
 }
 
 sovc_data.fn_capture = fn_capture;
 sovc_data.fn_error = fn_error;
 
 // create the capture thread
 {
  pthread_t video_capture_id;
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_create(&video_capture_id,NULL,video_capture_thread,NULL);
 }
 printf("create video capture thread end\n");
 return SOERR_NONE;
 
error:
 if(sovc_data.h264_fd>0)
  close(sovc_data.h264_fd);
 sovc_data.h264_fd = 0;
 
 return ret;
}

SOERR solcam_vc_stop()
{
 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED;
  
 if(sovc_data.status != SOLCAM_STATUS_RUNNING)
 {
  return SOERR_WRONG_STATUS;
 }
 
 sovc_data.status = SOLCAM_STATUS_STOPPED;
 
 while(sovc_data.stopped == 0)
 {
  usleep(50000);
 }
 
 if(sovc_data.h264_fd>0)
    {
        printf("close video device\n");
  close(sovc_data.h264_fd);
    }
 
 sovc_data.h264_fd = 0;
 
 return SOERR_NONE;
}

SOERR solcam_vc_get_status(SOLCAM_STATUS *status)
{
 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED;

 if(status == NULL)
  return SOERR_INVALID_PARAM;
 
 *status = sovc_data.status;
 
 return SOERR_NONE;
}

SOERR solcam_vc_uninit()

 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED;

 memset(&sovc_data, 0, sizeof(sovc_data));
 
 return SOERR_NONE;
}

 

#define MAX_SUPPORT_RES 16
static VideoRes  s_video_res[MAX_SUPPORT_RES];
static VideoResList svideo_res_list;

SOERR solcam_vc_list_res(VideoResList** res_list)
{
 struct v4l2_frmsizeenum size;
    struct v4l2_fmtdesc fmt;
    SOERR ret = SOERR_FAILED_LIST_RES;
   
    int h264_fd = 0;
   
    if(res_list == NULL)
  return SOERR_INVALID_PARAM;

 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED;
  
 if(sovc_data.status == SOLCAM_STATUS_RUNNING || sovc_data.h264_fd >0)
 {
  return SOERR_WRONG_STATUS;
 }
 if(!is_file_exist(sp_h264_dev))
 {
  printf("the sunny-webcam device is not been pluged\n");
  return SOERR_NO_CAM_DEVICE;
 }
 
 h264_fd = open(sp_h264_dev, O_RDWR);
 if(h264_fd <=0)
  return SOERR_FAILED_LIST_RES;
 
 memset(&svideo_res_list, 0, sizeof(VideoResList));
 svideo_res_list.video_res = s_video_res;
 
    fmt.index = 0;
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if((v4l2_ioctl (h264_fd, VIDIOC_ENUM_FMT, &fmt)<0))
    {
     printf("the sunny webcam device file ioctl failed.\n");
      goto exit;
    }

    memset (&size, 0, sizeof(struct v4l2_frmsizeenum));
    size.index = 0;
    size.pixel_format = fmt.pixelformat;
    if((v4l2_ioctl (h264_fd, VIDIOC_ENUM_FRAMESIZES, &size)<0))
    {
        printf("can not list the frame size!\n");
      goto exit;
    }
    if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE)
    {
        do
        {
            s_video_res[size.index].width = size.discrete.width;
            s_video_res[size.index].height = size.discrete.height;
            printf("got discrete frame size %dx%d, format: 0x%x\n",
                   size.discrete.width,
                   size.discrete.height,
                   size.pixel_format);
            size.index++;
            svideo_res_list.num_res++;
            if(size.index>=MAX_SUPPORT_RES)
            {
                break;
            }
        } while (v4l2_ioctl(h264_fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
        ret = SOERR_NONE;
    }
    else
    {
        printf("known type!\n");
        ret = SOERR_FAILED_LIST_RES;
    }
exit:

 if(svideo_res_list.num_res == 0)
 {
  return SOERR_FAILED_LIST_RES;
 }
 *res_list = &svideo_res_list;
 
 if(h264_fd>0)
  close(h264_fd);
  
 return ret;
}

SOERR solcam_vc_get_brightness(int* max_value, int *min_value, int *cur_value)
{
 struct v4l2_control control;
 
 if(max_value == NULL || min_value == NULL || cur_value == NULL)
  return SOERR_INVALID_PARAM;
 
 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED;
  
 if(sovc_data.h264_fd <= 0)
  return SOERR_UNINITED;
   
 control.id = V4L2_CID_BRIGHTNESS;

 if (v4l2_ioctl (sovc_data.h264_fd, VIDIOC_G_CTRL, &control) < 0)
 {
  printf("get brightness failed!\n");
  return SOERR_FAILED_GET_BRIGHTNESS;
 }
 *cur_value = control.value;
 *max_value = 0xFF;
 *min_value = 0;
 return SOERR_NONE;
}

SOERR solcam_vc_set_brightness(int brightness_value)
{
 struct v4l2_control control;
 
 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED;

 if(sovc_data.h264_fd <= 0)
  return SOERR_UNINITED;
   
 control.id = V4L2_CID_BRIGHTNESS;
 control.value = brightness_value;
 if (v4l2_ioctl (sovc_data.h264_fd, VIDIOC_S_CTRL, &control) < 0)
 {
  printf("set brightness failed!\n");
  return SOERR_FAILED_SET_BRIGHTNESS;
 }
 return SOERR_NONE;
}

SOERR solcam_vc_get_compquality( int* max_value, int *min_value, int *cur_value)
{
 if(max_value == NULL || min_value == NULL || cur_value == NULL)
  return SOERR_INVALID_PARAM;
  
 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED;

 if(sovc_data.h264_fd <= 0)
  return SOERR_UNINITED;
  
 if (v4l2_ioctl (sovc_data.h264_fd, VIDIOC_G_COMPQUALITY, cur_value) < 0)
 {
  printf("get compquality failed!\n");
  return SOERR_FAILED_GET_COMPQUALITY;
 }
 *max_value = 10000;
 *min_value = 0;
 return SOERR_NONE;
}

SOERR solcam_vc_set_compquality( int quality_value)
{
 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED;
  
 if(sovc_data.h264_fd <= 0)
  return SOERR_UNINITED;
  
 if (v4l2_ioctl (sovc_data.h264_fd, VIDIOC_S_COMPQUALITY, &quality_value) < 0)
 {
  printf("set compquality failed!\n");
  return SOERR_FAILED_SET_COMPQUALITY;
 }
 return SOERR_NONE;
}

SOERR solcam_vc_get_cur_framerate( double *cur_value)
{
 if(cur_value == NULL)
  return SOERR_INVALID_PARAM;

 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED;
  
 if(sovc_data.status != SOLCAM_STATUS_RUNNING)
 {
  return SOERR_WRONG_STATUS;
 }
 
    *cur_value = sovc_data.cur_framerate;
 
 return SOERR_NONE;
}

SOERR solcam_vc_get_cur_bitrate(int* cur_value)
{
 if(cur_value == NULL)
  return SOERR_INVALID_PARAM;

 if(sovc_data.init_id != INIT_ID)
  return SOERR_UNINITED; 
  
 if(sovc_data.status != SOLCAM_STATUS_RUNNING)
 {
  return SOERR_WRONG_STATUS;
 }
 
    *cur_value = sovc_data.cur_bitrate*8/1024;
 
 return SOERR_NONE;
}

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