• 4943阅读
  • 3回复

[提问]qt视频实时显示问题 [复制链接]

上一主题 下一主题
离线cesc1988
 
只看楼主 倒序阅读 楼主  发表于: 2011-11-10

在linux下用v4l2采集视频
但是程序运行后内存占用率越来越高 然后死机  
这是什么问题
求指教
一下是v4l2代码
#include "videodevice.h"
#include<QtDebug>
#include<QImage>

VideoDevice::VideoDevice(QString dev_name)
{
  this->dev_name = dev_name;
  this->fd = -1;
  this->buffers = NULL;
  this->n_buffers = 0;
  this->index = -1;

}

int VideoDevice::open_device()
{
  fd = open(dev_name.toStdString().c_str(), O_RDWR/*|O_NONBLOCK*/, 0);
  // fd = open(dev_name.toStdString().c_str(), O_RDWR|O_NONBLOCK, 0);

  if(-1 == fd)
  {
  qDebug("not open device successfully");
  return -1;
  }
  qDebug("open device successfully");
  return 0;
}

int VideoDevice::close_device()
{
  if(-1 == close(fd))
  {
  qDebug("fd close failed");
  return -1;
  }
  return 0;
}

int VideoDevice::init_device()
{
  v4l2_capability cap;
  v4l2_format fmt;
  qDebug("init star");
  if(-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap))
  {
  if(EINVAL == errno)
  {
  qDebug()<<dev_name<<" is no V4l2 device";
  }
  else
  {
  qDebug("VIDIOC_QUERYCAP is wrong");
  }
  return -1;
  }

  if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
  {
  qDebug()<<dev_name<<" is no video capture device";
  return -1;
  }

  if(!(cap.capabilities & V4L2_CAP_STREAMING))
  {
  qDebug()<<dev_name<<" does not support streaming i/o";
  return -1;
  }
  struct v4l2_fmtdesc fmt1;
  int ret;
  memset(&fmt1, 0, sizeof(fmt1));
  fmt1.index = 0;
  fmt1.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmt1)) == 0)//显示所有支持的格式
  {
  fmt1.index++;
  qDebug()<<"pixelformat ="<<char(fmt1.pixelformat & 0xFF)<<char((fmt1.pixelformat >> 8) & 0xFF)
  <<char((fmt1.pixelformat >> 16) & 0xFF)<<char((fmt1.pixelformat >> 24) & 0xFF)
  ;
  }
  CLEAR(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_YUYV;
  fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
  if(-1 == ioctl(fd, VIDIOC_S_FMT, &fmt))
  {
  qDebug("VIDIOC_S_FMT is not setted");
  return -1;
  }

  return 0;
}

int VideoDevice::init_mmap()
{
  v4l2_requestbuffers req;
  CLEAR(req);

  req.count = 4;
  req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  req.memory = V4L2_MEMORY_MMAP;

  if(-1 == ioctl(fd, VIDIOC_REQBUFS, &req))
  {
  if(EINVAL == errno)
  {
  qDebug()<<dev_name<<" does not support memory mapping";
  return -1;
  }
  else
  {
  qDebug("VIDIOC_REQBUFS is wrong");
  return -1;
  }
  }

  if(req.count < 2)
  {
  qDebug()<<dev_name<<"Insufficient buffer memory on ";
  return -1;
  }

  buffers = (buffer*)calloc(req.count, sizeof(*buffers));

  if(!buffers)
  {
  qDebug("out of memory");
  return -1;
  }

  for(n_buffers = 0; n_buffers < req.count; ++n_buffers)
  {
  v4l2_buffer buf;
  CLEAR(buf);

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

  if(-1 == ioctl(fd, VIDIOC_QUERYBUF, &buf))
  {
  qDebug("VIDIOC_QUERYBUF is wrong");
  return -1;
  }

  buffers[n_buffers].length = buf.length;
  buffers[n_buffers].start =
  mmap(NULL, // start anywhere
  buf.length,
  PROT_READ | PROT_WRITE,
  MAP_SHARED,
  fd, buf.m.offset);

  if(MAP_FAILED == buffers[n_buffers].start)
  {
  qDebug("mmap is wrong");
  return -1;
  }
  }
  return 0;

}

int VideoDevice::start_capturing()
{
  unsigned int i;
  for(i = 0; i < n_buffers; ++i)
  {
  v4l2_buffer buf;
  CLEAR(buf);

  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  buf.memory =V4L2_MEMORY_MMAP;
  buf.index = i;
  if(-1 == ioctl(fd, VIDIOC_QBUF, &buf))
  {

  qDebug("VIDIOC_QBUF is wrong");
  return -1;
  }
  }

  v4l2_buf_type type;
  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  if(-1 == ioctl(fd, VIDIOC_STREAMON, &type))
  {
  qDebug("VIDIOC_STREAMON is wrong");
  return -1;
  }
  return 0;
}

int VideoDevice::stop_capturing()
{
  v4l2_buf_type type;
  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  if(-1 == ioctl(fd, VIDIOC_STREAMOFF, &type))
  {
  emit display_error(tr("VIDIOC_STREAMOFF: %1").arg(QString(strerror(errno))));
  return -1;
  }
  return 0;
}

int VideoDevice::uninit_device()
{
  unsigned int i;
  for(i = 0; i < n_buffers; ++i)
  {
  if(-1 == munmap(buffers.start, buffers.length))
  {
  emit display_error(tr("munmap: %1").arg(QString(strerror(errno))));
  return -1;
  }

  }
  free(buffers);
  close(fd);
  return 0;
}

QImage* VideoDevice::get_frame()
{
  v4l2_buffer queue_buf;
  CLEAR(queue_buf);
  queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  queue_buf.memory = V4L2_MEMORY_MMAP;

  if(-1 == ioctl(fd, VIDIOC_DQBUF, &queue_buf))
  {
  switch(errno)
  {
  case EAGAIN:
  qDebug("dqbuf");
  case EIO:
  qDebug("EIO wrong");
  default:
  qDebug("VIDIOC_DQBUF is wrong");
  }
  }
// char *picturename="pic.jpg";
// if((file_fd = fopen(picturename, "wb+"))==NULL)
// {
// qDebug("create picture wrong");
// }
  qDebug()<<buffers[queue_buf.index].length;

  //fwrite(buffers[queue_buf.index].start, buffers[queue_buf.index].length, 1, file_fd);
  QImage *captureimage=new QImage(WIDTH,HEIGHT,QImage::Format_RGB32);
  uchar *bit=(uchar*)(buffers[queue_buf.index].start);
  int i=0,r,g,b,y0,y1,u0,v0,r0,g0,b0,r1,g1,b1;QRgb *point;
  for(int y=0;y<HEIGHT;y++)
  for(int x=0;x<WIDTH;x=x+2)
  {
  y0=bit;
  u0=bit[i+1];
  y1=bit[i+2];
  v0=bit[i+3];
// r0=y0+1.14*v0+0.5;
// g0=y0-0.39*u0-0.58*v0+0.5;
// b0=y0+2.03*u0+0.5;
// r1=y1+1.14*v0+0.5;
// g1=y1-0.39*u0-0.58*v0+0.5;
// b1=y1+2.03*u0+0.5;
  //////first way///////////
  /* r0=y0+1.4075*(v0-128)+0.5;
  g0=y0-0.3455*(u0-128)-0.7169*(v0-128)+0.5;
  b0=y0+1.779*(u0-128)+0.5;
  r1=y1+1.4075*(v0-128)+0.5;
  g1=y1-0.3455*(u0-128)-0.7169*(v0-128)+0.5;
  b1=y1+1.779*(u0-128)+0.5;*/
  //point=(QRgb*)(captureimage->scanLine(y)+x);
  //////second way///
  u0=u0-128;
  v0=v0-128;
  int rd=v0+((v0*103)>>8);
  int gd=((u0*88)>>8)+((v0*183)>>8);
  int bd=u0+((u0*198)>>8);
  r0=y0+rd;
  g0=y0-gd;
  b0=y0+bd;
  r1=y1+rd;
  g1=y1-gd;
  b1=y1+bd;
  if(r0>255) r0=255;
  if(r0<0) r0=0;
  if(r1>255) r1=255;
  if(r1<0) r1=0;
  captureimage->setPixel(x,y,qRgb(r0,g0,b0));
  // *point=qRgb(r0,g0,b0);
  captureimage->setPixel(x+1,y,qRgb(r1,g1,b1));
  // point=(QRgb*)(captureimage->scanLine(y)+x+1);
  //*point=qRgb(r1,g1,b1);
  i=i+4;
  }
  qDebug()<<y0<<u0<<v0<<r0<<g0<<b0<<i;
  if(ioctl(fd, VIDIOC_QBUF, &queue_buf)==-1) //再将其入列
  qDebug("failture VIDIOC_QBUF");
  /**** 修改的地方********/
  //free(&queue_buf);
  /***********/
  return captureimage;
}


int VideoDevice::unget_frame()
{
  if(index != -1)
  {
  v4l2_buffer queue_buf;
  CLEAR(queue_buf);

  queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  queue_buf.memory = V4L2_MEMORY_MMAP;
  queue_buf.index = index;

  if(-1 == ioctl(fd, VIDIOC_QBUF, &queue_buf))
  {
  emit display_error(tr("VIDIOC_QBUF: %1").arg(QString(strerror(errno))));
  return -1;
  }
  return 0;
  }
  return -1;
}

调用open_device->init_device->init_map->start_capturing->get_frame开始采集

离线wxj120bw

只看该作者 1楼 发表于: 2011-11-10
回 楼主(cesc1988) 的帖子
get_frame的captureimage你释放吗
离线cesc1988
只看该作者 2楼 发表于: 2011-11-25
回 1楼(wxj120bw) 的帖子
没有 但是我要返回这个图片啊  释放了就得不到了啊
离线wxj120bw

只看该作者 3楼 发表于: 2011-11-25
回 2楼(cesc1988) 的帖子
用完就释放
快速回复
限100 字节
 
上一个 下一个