⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vidinput_v4l2.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 3 页
字号:
  else {
    memcpy(buffer, videoBuffer[buf.index], buf.bytesused);
    if (bytesReturned != NULL)
      *bytesReturned = buf.bytesused;
  }

  PTRACE(8,"PVidInDev\tget frame data of " << buf.bytesused << "bytes, fd=" << videoFd);

  // requeue the buffer
  if (::ioctl(videoFd, VIDIOC_QBUF, &buf) < 0) {
    PTRACE(1,"PVidInDev\tQBUF failed : " << ::strerror(errno));
  }

  return TRUE;
}


// This video device does not support memory mapping - so use
// normal read process to extract a frame of video data.
BOOL PVideoInputDevice_V4L2::NormalReadProcess(BYTE * buffer, PINDEX * bytesReturned)
{ 
  if (!canRead)
    return FALSE;

  ssize_t bytesRead;

  do
    bytesRead = ::read(videoFd, buffer, frameBytes);
  while (bytesRead < 0 && errno == EINTR);

  if (bytesRead < 0) {
    
    PTRACE(1,"PVidInDev\tread failed (read = "<<bytesRead<< " expected " << frameBytes <<")");
    bytesRead = frameBytes;
  }

  if ((PINDEX)bytesRead != frameBytes) {
    PTRACE(1,"PVidInDev\tread returned fewer bytes than expected");
    // May result from a compressed format, otherwise indicates an error.
  }

  if (converter != NULL)
    return converter->ConvertInPlace(buffer, bytesReturned);

  if (bytesReturned != NULL)
    *bytesReturned = (PINDEX)bytesRead;

  return TRUE;
}

BOOL PVideoInputDevice_V4L2::VerifyHardwareFrameSize(unsigned width, unsigned height)
{
  struct v4l2_format videoFormat;
  videoFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  struct v4l2_streamparm streamParm;
  unsigned int fi_n = 0, fi_d = 0;
  streamParm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  // get the frame size
  if (::ioctl(videoFd, VIDIOC_G_FMT, &videoFormat) < 0) {
    PTRACE(1,"PVidInDev\tG_FMT failed : " << ::strerror(errno));
    return FALSE;
  }

  // get the frame rate so we can preserve it throughout the S_FMT call
  // Sidenote: V4L2 gives us the frame interval, i.e. 1/fps.
  if (::ioctl(videoFd, VIDIOC_G_PARM, &streamParm) == 0 &&
        streamParm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
    fi_n = streamParm.parm.capture.timeperframe.numerator;
    fi_d = streamParm.parm.capture.timeperframe.denominator;
  } else {
    PTRACE(1,"PVidInDev\tG_PARM failed (preserving frame rate may not work) : " << ::strerror(errno));
  }

  videoFormat.fmt.pix.width = width;
  videoFormat.fmt.pix.height = height;

  // set the frame size
  if (::ioctl(videoFd, VIDIOC_S_FMT, &videoFormat) < 0) {
    PTRACE(1,"PVidInDev\tS_FMT failed : " << ::strerror(errno));
    PTRACE(1,"\tused frame size of " << videoFormat.fmt.pix.width << "x" << videoFormat.fmt.pix.height);
    return FALSE;
  }

  // get the frame size again to be careful about broken drivers
  if (::ioctl(videoFd, VIDIOC_G_FMT, &videoFormat) < 0) {
    PTRACE(1,"PVidInDev\tG_FMT failed : " << ::strerror(errno));
    return FALSE;
  }

  if ((videoFormat.fmt.pix.width != width) || (videoFormat.fmt.pix.height != height)) {
    PTRACE(3,"PVidInDev\tframe size mismatch.");
    // allow the device to return actual frame size
    PVideoDevice::SetFrameSize(videoFormat.fmt.pix.width, videoFormat.fmt.pix.height);
    return FALSE;
  }

  // reset the frame rate because it may have been overridden by the call to S_FMT
  if (fi_n == 0 || fi_d == 0 || ::ioctl(videoFd, VIDIOC_S_PARM, &streamParm) < 0) {
    PTRACE(3,"PVidInDev\tunable to reset frame rate.");
  } else if (streamParm.parm.capture.timeperframe.numerator != fi_n ||
             streamParm.parm.capture.timeperframe.denominator  != fi_d) {
    PTRACE(3, "PVidInDev\tnew frame interval (" << streamParm.parm.capture.timeperframe.numerator
              << "/" << streamParm.parm.capture.timeperframe.denominator
              << ") differs from what was requested (" << fi_n << "/" << fi_d << ").");
  }

  frameBytes = videoFormat.fmt.pix.sizeimage;
  return TRUE;
}

/**
 * Query the current control setting
 * @param control is v4l2 control id (V4L2_CID_BRIGHTNESS, V4L2_CID_WHITENESS, ...)
 * @return  -1 control is unknown, or an error occured
 *         >=0 current value in a range [0-65535]
 */
int PVideoInputDevice_V4L2::GetControlCommon(unsigned int control, int *value) 
{
  if (!IsOpen())
    return -1;

  struct v4l2_queryctrl q;
  memset(&q, 0, sizeof(struct v4l2_queryctrl));
  q.id = control;
  if (::ioctl(videoFd, VIDIOC_QUERYCTRL, &q) < 0)
    return -1;

  struct v4l2_control c;
  memset(&c, 0, sizeof(struct v4l2_control));
  c.id = control;
  if (::ioctl(videoFd, VIDIOC_G_CTRL, &c) < 0)
    return -1;

  *value = ((c.value - q.minimum) * 65536) / ((q.maximum-q.minimum));
  return *value;
}

int PVideoInputDevice_V4L2::GetBrightness() 
{ 
  return GetControlCommon(V4L2_CID_BRIGHTNESS, &frameBrightness);
}

int PVideoInputDevice_V4L2::GetWhiteness() 
{
  return GetControlCommon(V4L2_CID_WHITENESS, &frameWhiteness);
}

int PVideoInputDevice_V4L2::GetColour() 
{ 
  return GetControlCommon(V4L2_CID_SATURATION, &frameColour);
}

int PVideoInputDevice_V4L2::GetContrast() 
{
  return GetControlCommon(V4L2_CID_CONTRAST, &frameContrast);
}

int PVideoInputDevice_V4L2::GetHue() 
{
  return GetControlCommon(V4L2_CID_HUE, &frameHue);
}

/**
 * Set a control to a new value
 *
 * @param control: V4L2_CID_BRIGHTNESS, V4L2_CID_WHITENESS, ...
 * @param newValue: 0-65535 Set this control to this range
 *                  -1 Set the default value
 * @return FALSE, if an error occur or the control is not supported
 */
BOOL PVideoInputDevice_V4L2::SetControlCommon(unsigned int control, int newValue)
{
  PTRACE(1,"PVidInDev\t" << __FUNCTION__  << "() videoFd=" << videoFd);
  if (!IsOpen())
    return FALSE;

  struct v4l2_queryctrl q;
  memset(&q, 0, sizeof(struct v4l2_queryctrl));
  q.id = control;
  if (::ioctl(videoFd, VIDIOC_QUERYCTRL, &q) < 0)
    return FALSE;

  struct v4l2_control c;
  memset(&c, 0, sizeof(struct v4l2_control));
  c.id = control;
  if (newValue < 0)
    c.value = q.default_value;
  else
    c.value = q.minimum + ((q.maximum-q.minimum) * newValue)/65535;

  if (::ioctl(videoFd, VIDIOC_S_CTRL, &c) < 0)
    return FALSE;

  return TRUE;
}

BOOL PVideoInputDevice_V4L2::SetBrightness(unsigned newBrightness) 
{ 
  if (!SetControlCommon(V4L2_CID_BRIGHTNESS, newBrightness))
    return FALSE;
  frameBrightness = newBrightness;
  return TRUE;
}

BOOL PVideoInputDevice_V4L2::SetWhiteness(unsigned newWhiteness) 
{ 
  if (!SetControlCommon(V4L2_CID_WHITENESS, newWhiteness))
    return FALSE;

  frameWhiteness = newWhiteness;
  return TRUE;
}

BOOL PVideoInputDevice_V4L2::SetColour(unsigned newColour) 
{ 
  if (!SetControlCommon(V4L2_CID_SATURATION, newColour))
    return FALSE;
  frameColour = newColour;
  return TRUE;
}

BOOL PVideoInputDevice_V4L2::SetContrast(unsigned newContrast) 
{ 
  if (!SetControlCommon(V4L2_CID_CONTRAST, newContrast))
    return FALSE;
  frameContrast = newContrast;
  return TRUE;
}

BOOL PVideoInputDevice_V4L2::SetHue(unsigned newHue) 
{
  if (!SetControlCommon(V4L2_CID_HUE, newHue))
    return FALSE;
  frameHue=newHue;
  return TRUE;
}

BOOL PVideoInputDevice_V4L2::GetParameters (int *whiteness, int *brightness, int *colour, int *contrast, int *hue)
{
  if (!IsOpen())
    return FALSE;

  frameWhiteness = -1;
  frameBrightness = -1;
  frameColour = -1;
  frameContrast = -1;
  frameHue = -1;
  GetWhiteness();
  GetBrightness();
  GetColour();
  GetContrast();
  GetHue();

  *whiteness  = frameWhiteness;
  *brightness = frameBrightness;
  *colour     = frameColour;
  *contrast   = frameContrast;
  *hue        = frameHue;

  return TRUE;
}

BOOL PVideoInputDevice_V4L2::TestAllFormats()
{
  return TRUE;
}



// this is used to get more userfriendly names:

void
V4L2Names::Update()
{
  PTRACE(1,"Detecting V4L2 devices");
  PDirectory   procvideo2_4("/proc/video/dev");
  PDirectory   procvideo2_6("/sys/class/video4linux");
  PDirectory * procvideo;
  PString      entry;
  PStringList  devlist;
  PString      oldDevName;
  // Try and guess kernel version
  if (procvideo2_6.Exists()) {
    kernelVersion = K2_6;
    procvideo=&procvideo2_6;
  }
  else if (procvideo2_4.Exists()) {
    kernelVersion=K2_4;
    procvideo=&procvideo2_4;
  } 
  else {
    kernelVersion=KUNKNOWN;
    procvideo=0;
  }
  inputDeviceNames.RemoveAll (); // flush the previous run
  if (procvideo) {
    PTRACE(2,"PV4L2Plugin\tdetected device metadata at "<<*procvideo);
    if ((kernelVersion==K2_6 && procvideo->Open(PFileInfo::SubDirectory) || 
        (procvideo->Open(PFileInfo::RegularFile)))) {
      do {
        entry = procvideo->GetEntryName();
        if ((entry.Left(5) == "video")) {
          PString thisDevice = "/dev/" + entry;
          int videoFd=::open((const char *)thisDevice, O_RDONLY | O_NONBLOCK);
          if ((videoFd > 0) || (errno == EBUSY)) {
            BOOL valid = FALSE;
            struct v4l2_capability videoCaps;
            memset(&videoCaps,0,sizeof(videoCaps));
            if ((errno == EBUSY) ||
                (::ioctl(videoFd, VIDIOC_QUERYCAP, &videoCaps) >= 0 &&
                (videoCaps.capabilities & V4L2_CAP_VIDEO_CAPTURE))) {
              PTRACE(1,"PV4L2Plugin\tdetected capture device " << videoCaps.card);
              valid = TRUE;
            }
            else {
              PTRACE(1,"PV4L2Plugin\t" << thisDevice << "is not deemed valid");
            }
            if (videoFd>0)
              ::close(videoFd);
            if(valid)
              inputDeviceNames += thisDevice;
          }
          else {
            PTRACE(1,"PV4L2Plugin\tcould not open " << thisDevice);
          }
        }
      } while (procvideo->Next());
    }
  }
  else {
    PTRACE(1,"Unable to detect v4l2 directory");
  }
  if (inputDeviceNames.GetSize() == 0) {
    POrdinalToString vid;
    ReadDeviceDirectory("/dev/", vid);

    for (PINDEX i = 0; i < vid.GetSize(); i++) {
      PINDEX cardnum = vid.GetKeyAt(i);
      int fd = ::open(vid[cardnum], O_RDONLY | O_NONBLOCK);
      if ((fd >= 0) || (errno == EBUSY)) {
        if (fd >= 0)
          ::close(fd);
        inputDeviceNames += vid[cardnum];
      }
    }
  }
  PopulateDictionary();
}

PString V4L2Names::BuildUserFriendly(PString devname)
{
  PString Result;

  int fd = ::open((const char *)devname, O_RDONLY);
  if(fd < 0) {
    return devname;
  }

  struct v4l2_capability videocap;
  memset(&videocap,0,sizeof(videocap));
  if (::ioctl(fd, VIDIOC_QUERYCAP, &videocap) < 0)  {
      ::close(fd);
      return devname;
    }
  
  ::close(fd);
  PString ufname((const char*)videocap.card);

  return ufname;
}

// End Of File ///////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -