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

📄 video_v4l2_source.cpp

📁 MPEG4音频视频压缩编码(含G.711/ACC/H.261等)
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * Use the m_release_index_mask to indicate which indexes need to * be released - note - there may be a problem if we don't release * in order given. */void CV4LVideoSource::ReleaseFrames (void){  uint8_t index = 0;  uint32_t index_mask = 1;  uint32_t released_mask;  int rc;  SDL_LockMutex(m_v4l_mutex);  released_mask = m_release_index_mask;  m_release_index_mask = 0;  SDL_UnlockMutex(m_v4l_mutex);  while (released_mask != 0 && index < 32) {    if ((index_mask & released_mask) != 0) {      if (m_waiting_frames_return) {	m_waiting_frames_return = false;	error_message("frame return");      }      struct v4l2_buffer buffer;      m_buffers[index].in_use = false;      if (m_source) {	buffer.index = index;	buffer.memory = V4L2_MEMORY_MMAP;	buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	buffer.flags = 0;	// it appears that some cards, some drivers require a QUERYBUF	// before the QBUF.  This code is designed to do so, but only if	// we need to	if (m_use_alternate_release) {	  rc = ioctl(m_videoDevice, VIDIOC_QUERYBUF, &buffer);	  if (rc < 0) {	    error_message("Failed to query video capture buffer status");	  }	}	rc = ioctl(m_videoDevice, VIDIOC_QBUF, &buffer);	if (rc < 0) {	  if (m_use_alternate_release) {	    error_message("Could not enqueue buffer to video capture queue");	  } else {	    rc = ioctl(m_videoDevice, VIDIOC_QUERYBUF, &buffer);	    if (rc < 0) {	      error_message("Failed to query video capture buffer status");	    }	    rc = ioctl(m_videoDevice, VIDIOC_QBUF, &buffer);	    if (rc < 0) {	      error_message("Failed to query video capture buffer status");	    } else {	      m_use_alternate_release = true;	    }	  }	}	//      debug_message("rel %d", index);      }     }    index_mask <<= 1;    index++;  }}void CV4LVideoSource::ProcessVideo(void){  // for efficiency, process ~1 second before returning to check for commands  Timestamp frameTimestamp;  for (int pass = 0; pass < m_maxPasses && m_stop_thread == false; pass++) {    // dequeue next frame from video capture buffer    int index = AcquireFrame(frameTimestamp);    if (index == -1) {      return;    }    m_buffers[index].in_use = true;    //debug_message("buffer %u in use", index);    u_int8_t* mallocedYuvImage = NULL;    u_int8_t* pY;    u_int8_t* pU;    u_int8_t* pV;    // perform colorspace conversion if necessary    switch (m_format) {    case V4L2_PIX_FMT_RGB24:    case V4L2_PIX_FMT_BGR24:      mallocedYuvImage = (u_int8_t*)Malloc(m_videoSrcYUVSize);      debug_message("converting to YUV420P from RGB");      pY = mallocedYuvImage;      pV = pY + m_videoSrcYSize;      pU = pV + m_videoSrcUVSize,        RGB2YUV(                m_videoSrcWidth,                m_videoSrcHeight,                (u_int8_t*)m_buffers[index].start,                pY,                pU,                pV,                1, 		m_format == V4L2_PIX_FMT_RGB24);      break;    case V4L2_PIX_FMT_YUYV:       mallocedYuvImage = (u_int8_t*)Malloc(m_videoSrcYUVSize);      //debug_message("converting to YUV420P from YUYV");      pY = mallocedYuvImage;      pU = pY + m_videoSrcYSize;      pV = pU + m_videoSrcUVSize;      convert_yuyv_to_yuv420p(pY, 			      (const uint8_t *)m_buffers[index].start,			      m_videoSrcWidth,			      m_videoSrcHeight);      break;    case V4L2_PIX_FMT_UYVY:      mallocedYuvImage = (u_int8_t*)Malloc(m_videoSrcYUVSize);      //debug_message("converting to YUV420P from YUYV");      pY = mallocedYuvImage;      pU = pY + m_videoSrcYSize;      pV = pU + m_videoSrcUVSize;      convert_uyvy_to_yuv420p(pY,			      (const uint8_t *)m_buffers[index].start,			      m_videoSrcWidth,			      m_videoSrcHeight);      break;    case V4L2_PIX_FMT_YYUV:      mallocedYuvImage = (u_int8_t*)Malloc(m_videoSrcYUVSize);      //debug_message("converting to YUV420P from YUYV");      pY = mallocedYuvImage;      pU = pY + m_videoSrcYSize;      pV = pU + m_videoSrcUVSize;      convert_yyuv_to_yuv420p(pY,			      (const uint8_t *)m_buffers[index].start,			      m_videoSrcWidth,			      m_videoSrcHeight);      break;    case V4L2_PIX_FMT_NV12:      mallocedYuvImage = (u_int8_t*)Malloc(m_videoSrcYUVSize);      //debug_message("converting to YUV420P from YUYV");      pY = mallocedYuvImage;      pU = pY + m_videoSrcYSize;      pV = pU + m_videoSrcUVSize;      convert_nv12_to_yuv420p(pY,			      (const uint8_t *)m_buffers[index].start,			      m_videoSrcYSize,			      m_videoSrcWidth,			      m_videoSrcHeight);      break;    default:#if 0      // we would need the below if we were going to switch       // video - this is a problem with the       mallocedYuvImage = (u_int8_t*)Malloc(m_videoSrcYUVSize);      pY = (u_int8_t*)mallocedYuvImage;      memcpy(pY, m_buffers[index].start, m_videoSrcYUVSize);#else      pY = (u_int8_t*)m_buffers[index].start;#endif      pU = pY + m_u_offset;      pV = pY + m_v_offset;    }    if (m_decimate_filter) {      video_filter_decimate(pY,			    m_videoSrcWidth,			    m_videoSrcHeight);    }    yuv_media_frame_t *yuv = MALLOC_STRUCTURE(yuv_media_frame_t);    yuv->y = pY;    yuv->u = pU;    yuv->v = pV;    yuv->y_stride = m_videoSrcWidth;    yuv->uv_stride = m_videoSrcWidth >> 1;    yuv->w = m_videoSrcWidth;    yuv->h = m_videoSrcHeight;    yuv->hardware = this;    yuv->hardware_version = m_hardware_version;    yuv->hardware_index = index;    if (m_videoWantKeyFrame && frameTimestamp >= m_audioStartTimestamp) {      yuv->force_iframe = true;      m_videoWantKeyFrame = false;      debug_message("Frame "U64" request key frame", frameTimestamp);    } else       yuv->force_iframe = false;    yuv->free_y = (mallocedYuvImage != NULL);    CMediaFrame *frame = new CMediaFrame(YUVVIDEOFRAME,					 yuv,					 0,					 frameTimestamp);    frame->SetMediaFreeFunction(c_ReleaseFrame);    ForwardFrame(frame);    //debug_message("video source forward");    // enqueue the frame to video capture buffer    if (mallocedYuvImage != NULL) {      IndicateReleaseFrame(index);    }  }}bool CV4LVideoSource::InitialVideoProbe(CLiveConfig* pConfig){  static const char* devices[] = {    "/dev/video",     "/dev/video0",     "/dev/video1",     "/dev/video2",     "/dev/video3"  };  const char* deviceName = pConfig->GetStringValue(CONFIG_VIDEO_SOURCE_NAME);  CVideoCapabilities* pVideoCaps;  // first try the device we're configured with  pVideoCaps = new CVideoCapabilities(deviceName);  if (pVideoCaps->IsValid()) {    pConfig->m_videoCapabilities = pVideoCaps;    return true;  }  delete pVideoCaps;  // no luck, go searching  for (unsigned int i = 0; i < sizeof(devices) / sizeof(*devices); i++) {    // don't waste time trying something that's already failed    if (!strcmp(devices[i], deviceName)) {      continue;    }     pVideoCaps = new CVideoCapabilities(devices[i]);    if (pVideoCaps->IsValid()) {      pConfig->SetStringValue(CONFIG_VIDEO_SOURCE_NAME, devices[i]);      pConfig->m_videoCapabilities = pVideoCaps;      return true;    }		    delete pVideoCaps;  }  return false;}bool CVideoCapabilities::ProbeDevice(){  int rc, i;  // open the video device  int videoDevice = open(m_deviceName, O_RDWR);  if (videoDevice < 0) return false;  m_canOpen = true;  // query device capabilities  struct v4l2_capability capability;  memset(&capability, 0, sizeof(capability));  rc = ioctl(videoDevice, VIDIOC_QUERYCAP, &capability);  if (rc < 0) {    error_message("Failed to query video capabilities for %s", m_deviceName);    close(videoDevice);    return false;  }  // make sure device supports video capture  if (!(capability.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {    error_message("Device %s is not capable of video capture!", m_deviceName);    close(videoDevice);    return false;  }  m_canCapture = true;  m_driverName = strdup((char*)capability.driver);  m_hasAudio = capability.capabilities & (V4L2_CAP_AUDIO | V4L2_CAP_TUNER);  struct v4l2_input input;  memset(&input, 0, sizeof(input));  // get the number of inputs  for(i=0; ; i++) {    input.index = i;    rc = ioctl(videoDevice, VIDIOC_ENUMINPUT, &input);    if (rc < 0) {      if (errno == EINVAL) break;    }  }  m_numInputs = i;  m_inputNames = (char**)malloc(m_numInputs * sizeof(char*));  memset(m_inputNames, 0, m_numInputs * sizeof(char*));  m_inputHasTuners = (bool*)malloc(m_numInputs * sizeof(bool));  memset(m_inputHasTuners, 0, m_numInputs * sizeof(bool));  m_inputTunerSignalTypes = (u_int8_t*)malloc(m_numInputs * sizeof(u_int8_t));  memset(m_inputTunerSignalTypes, 0, m_numInputs * sizeof(u_int8_t));    // enumerate all inputs  for(i=0; i<m_numInputs; i++) {    input.index = i;    rc = ioctl(videoDevice, VIDIOC_ENUMINPUT, &input);    if (rc >= 0) {      m_inputNames[i] = strdup((char*)input.name);    } else {      m_inputNames[i] = strdup("Unknown input");      error_message("Failed to enumerate video input %d for %s",                    i, m_deviceName);      continue;    }    error_message("type %d %s type %x", i, m_inputNames[i], input.type);    if (input.type == V4L2_INPUT_TYPE_TUNER) {      error_message("Has tuner");      m_inputHasTuners[i] = true;      if (input.std & V4L2_STD_PAL) m_inputTunerSignalTypes[i] |= 0x1;      if (input.std & V4L2_STD_NTSC) m_inputTunerSignalTypes[i] |= 0x2;      if (input.std & V4L2_STD_SECAM) m_inputTunerSignalTypes[i] |= 0x4;    }  }  close(videoDevice);  return true;}static const char *signals[] = {  "PAL", "NTSC", "SECAM",};void CVideoCapabilities::Display (CLiveConfig *pConfig,				  char *msg, 				  uint32_t max_len){  uint32_t port = pConfig->GetIntegerValue(CONFIG_VIDEO_INPUT);  if (port >= m_numInputs) {    snprintf(msg, max_len, "Video port has illegal value");    return;  }  if (m_inputHasTuners[port] == false) {    snprintf(msg, max_len, 	     "%s, %ux%u, %s, %s",	     pConfig->GetStringValue(CONFIG_VIDEO_SOURCE_NAME),	     pConfig->m_videoWidth,	     pConfig->m_videoHeight,	     signals[pConfig->GetIntegerValue(CONFIG_VIDEO_SIGNAL)],	     m_inputNames[port]);  } else {    snprintf(msg, max_len, 	     "%s, %ux%u, %s, %s, %s, channel %s",	     pConfig->GetStringValue(CONFIG_VIDEO_SOURCE_NAME),	     pConfig->m_videoWidth,	     pConfig->m_videoHeight,	     signals[pConfig->GetIntegerValue(CONFIG_VIDEO_SIGNAL)],	     m_inputNames[port],	     chanlists[pConfig->GetIntegerValue(CONFIG_VIDEO_CHANNEL_LIST_INDEX)].name,	     chanlists[pConfig->GetIntegerValue(CONFIG_VIDEO_CHANNEL_LIST_INDEX)].list[pConfig->GetIntegerValue(CONFIG_VIDEO_CHANNEL_INDEX)].name	     );  }}

⌨️ 快捷键说明

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