📄 video_v4l2_source.cpp
字号:
formats[ix], format.fmt.pix.height, height); } } if (pass == false) { error_message("Failed to select any video formats for %s", deviceName); goto failure; } //turn auto exposure off for ovfx2 camera // int exposure=0; // ioctl(m_videoDevice, VIDIOCCAPTURE, &exposure); switch (m_format) { case V4L2_PIX_FMT_YVU420: m_v_offset = m_videoSrcYSize; m_u_offset = m_videoSrcYSize + m_videoSrcUVSize; debug_message("format is YVU 4:2:0 %ux%u", width, height); break; case V4L2_PIX_FMT_YUV420: m_u_offset = m_videoSrcYSize; m_v_offset = m_videoSrcYSize + m_videoSrcUVSize; debug_message("format is YUV 4:2:0 %ux%u", width, height); break; case V4L2_PIX_FMT_RGB24: debug_message("format is RGB24 %ux%u", width, height); break; case V4L2_PIX_FMT_BGR24: debug_message("format is BGR24 %ux%u", width, height); break; case V4L2_PIX_FMT_YUYV: debug_message("format is YUYV %ux%u", width, height); break; case V4L2_PIX_FMT_UYVY: debug_message("format is UYUV %ux%u", width, height); break; case V4L2_PIX_FMT_YYUV: debug_message("format is YYUV %ux%u", width, height); break; case V4L2_PIX_FMT_NV12: debug_message("format is NV12 %ux%u", width, height); } // allocate the desired number of buffers m_release_index_mask = 0; struct v4l2_requestbuffers reqbuf; memset(&reqbuf, 0, sizeof(reqbuf)); reqbuf.count = MIN(m_pConfig->GetIntegerValue(CONFIG_VIDEO_CAP_BUFF_COUNT), 32); reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuf.memory = V4L2_MEMORY_MMAP; rc = ioctl(m_videoDevice, VIDIOC_REQBUFS, &reqbuf); if (rc < 0 || reqbuf.count < 1) { error_message("Failed to allocate buffers for %s", deviceName); return false; } // map the video capture buffers m_buffers_count = reqbuf.count; m_buffers = (capture_buffer_t*)calloc(reqbuf.count, sizeof(capture_buffer_t)); if (m_buffers == NULL) { error_message("Failed to allocate memory for m_buffers"); return false; } for(uint32_t ix=0; ix<reqbuf.count; ix++) { struct v4l2_buffer buffer; memset(&buffer, 0, sizeof(buffer)); // cpn24 buffer.index = ix; buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; // cpn24 rc = ioctl(m_videoDevice, VIDIOC_QUERYBUF, &buffer); if (rc < 0) { error_message("Failed to query video capture buffer status for %s", deviceName); goto failure; } m_buffers[ix].length = buffer.length; m_buffers[ix].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, m_videoDevice, buffer.m.offset); if (m_buffers[ix].start == MAP_FAILED) { error_message("Failed to map video capture buffer for %s", deviceName); goto failure; } //enqueue the mapped buffer rc = ioctl(m_videoDevice, VIDIOC_QBUF, &buffer); if (rc < 0) { error_message("Failed to enqueue video capture buffer status for %s", deviceName); goto failure; } } SetPictureControls(); if (capability.capabilities & (V4L2_CAP_AUDIO | V4L2_CAP_TUNER)) { SetVideoAudioMute(false); } // start video capture rc = ioctl(m_videoDevice, VIDIOC_STREAMON, &buftype); if (rc < 0) { error_message("Failed to start video capture for %s", deviceName); perror("Reason"); goto failure; }#if 0 // start video capture again rc = ioctl(m_videoDevice, VIDIOC_STREAMON, &buftype); if (rc < 0) { error_message("Failed to start video capture again for %s", deviceName); perror("Again Reason"); goto failure; }#endif return true; failure: if (m_buffers) { for (uint32_t i = 0; i < m_buffers_count; i++) { if (m_buffers[i].start) munmap(m_buffers[i].start, m_buffers[i].length); } free(m_buffers); } close(m_videoDevice); m_videoDevice = -1; return false;}void CV4LVideoSource::ReleaseDevice(){ SetVideoAudioMute(true); // stop video capture int buftype = V4L2_BUF_TYPE_VIDEO_CAPTURE; int rc = ioctl(m_videoDevice, VIDIOC_STREAMOFF, &buftype); if (rc < 0) { error_message("Failed to stop video capture"); } close(m_videoDevice); m_videoDevice = -1;}bool CV4LVideoSource::ReleaseBuffers (void){ if (m_buffers == NULL) return true; ReleaseFrames(); // release device resources bool have_buffers = false; for (uint32_t i = 0; i < m_buffers_count; i++) { if (m_buffers[i].start) { if (m_buffers[i].in_use) { have_buffers = true; error_message("buffer %u still in use", i); } else { munmap(m_buffers[i].start, m_buffers[i].length); m_buffers[i].start = NULL; } } } if (have_buffers) return false; error_message("All buffers released"); free(m_buffers); m_buffers = NULL; return true;} void CV4LVideoSource::SetVideoAudioMute(bool mute){ if (!m_pConfig->m_videoCapabilities) return; CVideoCapabilities *vc = (CVideoCapabilities *)m_pConfig->m_videoCapabilities; if ( !vc->m_hasAudio) { return; } int rc; struct v4l2_control control; control.id = V4L2_CID_AUDIO_MUTE; control.value = 0; rc = ioctl(m_videoDevice, VIDIOC_G_CTRL, &control); if (rc < 0) { error_message("V4L2_CID_AUDIO_MUTE not supported"); } else { control.value = mute ? true : false; rc = ioctl(m_videoDevice, VIDIOC_S_CTRL, &control); if (rc < 0) { error_message("Couldn't set audio mute for %s ", m_pConfig->m_videoCapabilities->m_deviceName); } }}bool CV4LVideoSource::SetPictureControls(){ if (m_videoDevice == -1) return false; int rc; struct v4l2_control control; memset(&control, 0, sizeof(control));/* //autoexposure control.id = V4L2_CID_AUTOGAIN; control.value = 0; ((m_pConfig->GetIntegerValue(CONFIG_VIDEO_AUTOGAIN) * 0xFFFF) /100);// Changes to 1 to turn it on rc = ioctl(m_videoDevice, VIDIOC_S_CTRL, &control); //autobrightness control.id = V4L2_CID_AUTO_WHITE_BALANCE; control.value = 0; ((m_pConfig->GetIntegerValue(CONFIG_VIDEO_AUTO_WHITE_BALANCE) * 0xFFFF) /100);// Changes to 1 to turn it on rc = ioctl(m_videoDevice, VIDIOC_S_CTRL, &control); //Turn on flipvert control.id = V4L2_CID_VFLIP; control.value = 0; ((m_pConfig->GetIntegerValue(CONFIG_VIDEO_VFLIP) * 0xFFFF) /100);// Changes to 1 to turn it on rc = ioctl(m_videoDevice, VIDIOC_S_CTRL, &control);*/ // brightness control.id = V4L2_CID_BRIGHTNESS; rc = ioctl(m_videoDevice, VIDIOC_G_CTRL, &control); if (rc < 0) { error_message("V4L2_CID_BRIGHTNESS not supported"); } else { control.value = (int) ((m_pConfig->GetIntegerValue(CONFIG_VIDEO_BRIGHTNESS) * 0xFFFF) / 100); rc = ioctl(m_videoDevice, VIDIOC_S_CTRL, &control); if (rc < 0) { error_message("Couldn't set brightness level"); return false; } } // hue control.id = V4L2_CID_HUE; rc = ioctl(m_videoDevice, VIDIOC_G_CTRL, &control); if (rc < 0) { error_message("V4L2_CID_HUE not supported"); } else { control.value = (int) ((m_pConfig->GetIntegerValue(CONFIG_VIDEO_HUE) * 0xFFFF) / 100); rc = ioctl(m_videoDevice, VIDIOC_S_CTRL, &control); if (rc < 0) { error_message("Couldn't set hue level"); return false; } } // color control.id = V4L2_CID_SATURATION; rc = ioctl(m_videoDevice, VIDIOC_G_CTRL, &control); if (rc < 0) { error_message("V4L2_CID_SATURATION not supported"); } else { control.value = (int) ((m_pConfig->GetIntegerValue(CONFIG_VIDEO_COLOR) * 0xFFFF) / 100); rc = ioctl(m_videoDevice, VIDIOC_S_CTRL, &control); if (rc < 0) { error_message("Couldn't set saturation level"); return false; } } // contrast control.id = V4L2_CID_CONTRAST; rc = ioctl(m_videoDevice, VIDIOC_G_CTRL, &control); if (rc < 0) { error_message("V4L2_CID_CONTRAST not supported"); } else { control.value = (int) ((m_pConfig->GetIntegerValue(CONFIG_VIDEO_CONTRAST) * 0xFFFF) / 100); rc = ioctl(m_videoDevice, VIDIOC_S_CTRL, &control); if (rc < 0) { error_message("Couldn't set contrast level"); return false; } } return true;}int8_t CV4LVideoSource::AcquireFrame(Timestamp &frameTimestamp){ struct v4l2_buffer buffer; ReleaseFrames(); // if we're still waiting to release frames, there's no need // to get another error buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; int rc = ioctl(m_videoDevice, VIDIOC_DQBUF, &buffer); if (rc != 0) { error_message("error %d errno %d %s", rc, errno, strerror(errno)); m_waiting_frames_return = true; return -1; } // debug_message("acq %d", buffer.index); frameTimestamp = GetTimestampFromTimeval(&(buffer.timestamp)); return buffer.index;}void c_ReleaseFrame (void *f){ yuv_media_frame_t *yuv = (yuv_media_frame_t *)f; if (yuv->free_y) { CHECK_AND_FREE(yuv->y); } else { CV4LVideoSource *s = (CV4LVideoSource *)yuv->hardware; if (s->IsHardwareVersion(yuv->hardware_version)) { s->IndicateReleaseFrame(yuv->hardware_index); } else { // need to free the buffer //munmap(yuv->y, ) // hit the semaphore... s->ReleaseOldFrame(yuv->hardware_version, yuv->hardware_index); } } free(yuv);}void CV4LVideoSource::ReleaseOldFrame (uint hardware_version, uint8_t index){ SDL_LockMutex(m_v4l_mutex); unreleased_capture_buffers_t *p = m_unreleased_buffers_list, *q = NULL; while (p != NULL && p->hardware_version != hardware_version) { q = p; p = p->next; } if (p != NULL) { debug_message("release version %u index %u", hardware_version, index); p->buffer_list[index].in_use = false; munmap(p->buffer_list[index].start, p->buffer_list[index].length); p->buffer_list[index].start = NULL; bool have_one = false; for (uint32_t ix = 0; ix < m_buffers_count && have_one == false; ix++) { have_one = p->buffer_list[index].start != NULL; } if (have_one) { q->next = p->next; free(p->buffer_list); free(p); } } else debug_message("couldn't release version %u index %u", hardware_version, index); SDL_UnlockMutex(m_v4l_mutex);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -