根据国嵌的程序改的v4l2程序

/* 服务端程序 server.c */ 
//WB
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <linux/types.h>
#include <linux/videodev2.h>
#include <setjmp.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/socket.h> 
#include <netinet/in.h>
#include "convert.h"


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


#define SERVER_PORT 8888 
#define WIDTH 160
#define HEIGHT 120 
#define FRAME_COUNT 1 //?建?????
#define FRAME_IDLE 60
T264_t* m_t264;
T264_param_t m_param;
char* m_pSrc;
char* m_pDst;
int* m_lDstSize;
char* m_pPoolData;




#define USB_VIDEO "/dev/video0"






typedef struct VideoBuffer  //定义一个结构体来映射每个缓冲帧
{
  void   *start;
  size_t  length;
}VideoBuffer;


static int cam_fd;
static VideoBuffer *buffers = NULL;
static unsigned int numBufs = 0;


static int read_video(int index)
{
  struct v4l2_buffer buf;
  
  memset(&buf,0,sizeof(buf));
  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  buf.memory = V4L2_MEMORY_MMAP;
  buf.index = index;
  //VIDIOC_DQBUF 从队列中取出帧
  if (ioctl(cam_fd, VIDIOC_DQBUF, &buf) == -1)
    return -1;
 /*图像处理  
process_image(buffers[buf.index].start);  */
  //将取出的缓冲帧放回缓冲区 
  if (ioctl(cam_fd, VIDIOC_QBUF, &buf) == -1) 
    return -1;
  
  return 0;
}








static int init_video(int w,int h) /* bpp == bytes per pixel*/
{
  
  
  /*设备的打开*/
  cam_fd = open( USB_VIDEO, O_RDWR );
  if(cam_fd<0 )
    printf("Can't open video device\n");
/* 使用IOCTL命令VIDIOCGCAP,获取摄像头的基本信息,如最大,最小分辨率*/
  
  struct v4l2_capability cap;


  if (ioctl (cam_fd, VIDIOC_QUERYCAP, &cap) == -1) 
  {
    printf("Get camara capability is fail.\n");
    return -1;
  }
  
  printf("camara driver: %s\n", cap.driver);
  printf("camara card: %s\n", cap.card);
  printf("camara bus info: %s\n", cap.bus_info);
  printf("camara version: %d\n", cap.version);
   printf("4\n");
  if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) //是否支持图像获取
  {
    printf("Camara does not support VIDEO CAPTURE.\n");
    return -1;
  }
   printf("5\n");
  if (!(cap.capabilities & V4L2_CAP_STREAMING)) //I/O的读写控制流
  {
    printf("Camara does not support STREAMING.\n");
    return -1;
  }
  printf("6\n");
  
  struct v4l2_format fmt;
  
  memset(&fmt, 0, sizeof(fmt));
  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  fmt.fmt.pix.width = WIDTH;//帧宽  帧高  单位像素 
  fmt.fmt.pix.height = HEIGHT;
  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
  fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
  if (ioctl(cam_fd, VIDIOC_S_FMT, &fmt) == -1)//检查是否支持V4L2_PIX_FMT_MJPEG  格式
  {
    printf("Camara set fmt is errror.\n");
    return -1;
  }
  printf("7\n");
  struct v4l2_requestbuffers req;
  enum v4l2_buf_type type;   //enum v4l2_buf_type type; //数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
  struct v4l2_buffer buf;
  memset(&req, 0, sizeof (req));
  req.count = FRAME_COUNT;缓存数量,也就是说在缓存队列里保持多少张照片   申请一个拥有FRAME_COUNT个缓冲帧的缓冲区
  req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  req.memory = V4L2_MEMORY_MMAP;
  if (ioctl(cam_fd, VIDIOC_REQBUFS, &req) < 0)
  {
    printf("VIDIOC_REQBUFS failed\n");
    return -1;
  }
  printf("8\n");
   buffers = (VideoBuffer *)calloc(req.count, sizeof(*buffers));
  // 映射
  printf("9\n");
  for (numBufs = 0; numBufs < req.count; numBufs++) 
  {
   printf("10\n");
    memset(&buf, 0, sizeof(buf));
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    buf.index = numBufs;
    // 查询序号为numBufs的缓冲区,得到其起始物理地址和大小  
    if (ioctl(cam_fd, VIDIOC_QUERYBUF, &buf) == -1)    // 读取缓存
      return -1;
buffers[numBufs].length = buf.length;
// 转换成相对地址
//映射内存 
printf("11\n");
    buffers[numBufs].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, cam_fd, buf.m.offset);//返回所分配的内存空间的首地址。
/*
void *mmap(void*addr, size_t length, int prot, int flags, int fd, off_t offset);
//addr 映射起始地址,一般为NULL ,让内核自动选择
//length 被映射内存块的长度
//prot 标志映射后能否被读写,其值为PROT_EXEC,PROT_READ,PROT_WRITE,PROT_NONE
//flags 确定此内存映射能否被其他进程共享,MAP_SHARED,MAP_PRIVATE
//fd,offset, 确定被映射的内存地址
返回成功映射后的地址,不成功返回MAP_FAILED ((void*)-1);*/
    if (buffers[numBufs].start == MAP_FAILED)
      return -1;
  printf("12\n");
    //VIDIOC_QBUF// 把帧放入队列  
//VIDIOC_DQBUF// 从队列中取出帧
    if (ioctl(cam_fd, VIDIOC_QBUF, &buf) == -1)// 放入缓存队列
      return -1;
 printf("13\n");
  }
  // 在开始之前,还应当把缓冲帧放入缓冲队列:
  
  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   printf("14\n");
  if (ioctl(cam_fd, VIDIOC_STREAMON, &type) < 0) //开始视屏流数据的采集
  {
    printf("VIDIOC_STREAMON error\n");
    return -1;
  }
  printf("15\n");
 //InitLookupTable();//实现的函数调用有InitLookupTable()用于初始化色彩空间转换;
  return 0;
  
}




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


memset(param, 0, sizeof(*param));
fgets(line, 254, fd); sscanf(line,"%d", &b);
if (b != 4)
{
printf("wrong param file version, expect v4.0\n");
exit(-1);
}
fgets(line, 254, fd); sscanf(line,"%d", &param->width);
fgets(line, 254, fd); sscanf(line,"%d", &param->height);
fgets(line, 254, fd); sscanf(line,"%d", &param->search_x);
fgets(line, 254, fd); sscanf(line,"%d", &param->search_y);
fgets(line, 254, fd); sscanf(line,"%d", &total_no);
fgets(line, 254, fd); sscanf(line,"%d", &param->iframe);
fgets(line, 254, fd); sscanf(line,"%d", &param->idrframe);
fgets(line, 254, fd); sscanf(line,"%d", &param->b_num);
fgets(line, 254, fd); sscanf(line,"%d", &param->ref_num);
fgets(line, 254, fd); sscanf(line,"%d", &param->enable_rc);
fgets(line, 254, fd); sscanf(line,"%d", &param->bitrate);
fgets(line, 254, fd); sscanf(line,"%f", &param->framerate);
fgets(line, 254, fd); sscanf(line,"%d", &param->qp);
fgets(line, 254, fd); sscanf(line,"%d", &param->min_qp);
fgets(line, 254, fd); sscanf(line,"%d", &param->max_qp);
fgets(line, 254, fd); sscanf(line,"%d", &param->enable_stat);
fgets(line, 254, fd); sscanf(line,"%d", &param->disable_filter);
fgets(line, 254, fd); sscanf(line,"%d", &param->aspect_ratio);
fgets(line, 254, fd); sscanf(line,"%d", &param->video_format);
fgets(line, 254, fd); sscanf(line,"%d", &param->luma_coeff_cost);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_INTRA16x16) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_INTRA4x4) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_INTRAININTER) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_HALFPEL) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_QUARTPEL) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_SUBBLOCK) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_FULLSEARCH) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_DIAMONDSEACH) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_FORCEBLOCKSIZE) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_FASTINTERPOLATE) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_SAD) * b;
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_EXTRASUBPELSEARCH) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->flags |= (USE_SCENEDETECT) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_16x16P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_16x8P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_8x16P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_8x8P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_8x4P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_4x8P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_4x4P) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_16x16B) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_16x8B) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_8x16B) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &b);
param->block_size |= (SEARCH_8x8B) * (!!b);
fgets(line, 254, fd); sscanf(line,"%d", &param->cpu);
fgets(line, 254, fd); sscanf(line, "%d", &param->cabac);


// fgets(line, 254, fd); sscanf(line,"%s", src_path);
// fgets(line, 254, fd); sscanf(line,"%s", out_path);
// fgets(line, 254, fd); sscanf(line,"%s", rec_path);
// param->rec_name = rec_path;


fclose(fd);
}




void init_encoder()
{
//编码准备
const char* paramfile = "fastspeed.txt";
/*获取fastspeed.txt文件信息*/
init_param(&m_param, paramfile);
printf("1\n");
m_param.direct_flag = 1;
/*t264编码的打开*/
//T264_t *T264_open(&param) 根据param 参数配置,打开并初始化一个编码器实例,返回编码器实例指针,可以当成句柄理解。
m_t264 = T264_open(&m_param);
m_lDstSize  = m_param.height * m_param.width + (m_param.height * m_param.width >> 1);
  /*分配t264解码后数据存放的内存*/
m_pDst = (uint8_t*)T264_malloc(m_lDstSize, CACHE_SIZE); // uint8_t *T264_malloc(size, CACHE_SIZE),分配内存,大小为 size,返回内存区指针。
printf("2\n");
/*分配内存用于存放一帧数据长度的数据*/
m_pPoolData = malloc(m_param.width*m_param.height*3/2); 
printf("3\n");
}

void udps_respon(int sockfd,int w,int h) 

struct sockaddr_in addrsrc;
struct sockaddr_in addrdst; 
int addrlen,n; 

int32_t iActualLen;
int row_stride = w*3*h/2;


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


while(1) 

/*数据的采集*/
if(read_video(0))
exit(1);

/*对采集到的数据通过H264编码*/
iActualLen = T264_encode(m_t264,buffers[0].start, m_pDst, row_stride);
printf("encoded:%d, %d bytes.\n",row_stride,iActualLen); 
/*frame_num:存放帧号*/
memcpy(m_pPoolData,&m_t264->frame_num,1);
/*m_pDst解码后的数据*/
memcpy(m_pPoolData+1, m_pDst, iActualLen);
iActualLen++;
/*使用UDP协议发送编码后的数据到客服端*/
sendto(sockfd,m_pPoolData,iActualLen,0,(struct sockaddr*)&addrdst,sizeof(struct sockaddr_in));






void free_dev()
{
  printf("free device\n");
  close(cam_fd);
}


/*主函数入口*/
int main(void) 
{
int sockfd; 
struct sockaddr_in addr;


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


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


if(sockfd<0) 
{
printf("0-");
printf("Socket Error\n"); 
exit(1); 



bzero(&addr,sizeof(struct sockaddr_in)); 
addr.sin_family=AF_INET; 
addr.sin_addr.s_addr=htonl(INADDR_ANY); 
addr.sin_port=htons(SERVER_PORT); 
/*套接字绑定*/
if(bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in))<0 ) 

printf("Socket Error\n"); 
exit(1); 

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


atexit(&free_dev );  //(即main执行结束后调用的函数)
/*采集数据前的初始化函数*/
if (init_video(m_param.width,m_param.height))
  {
        printf("init_vodeo Error\n"); 
exit(1); 
  }
  



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

close(sockfd); 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值