Skip to content

Instantly share code, notes, and snippets.

@lp6m lp6m/pcam.cpp
Created Dec 6, 2018

Embed
What would you like to do?
永久財産
/*
before run this code, you should run the following commands.
media-ctl -d /dev/media0 -V '"ov5640 2-003c":0 [fmt:UYVY/'1920x1080'@1/'15' field:none]'
media-ctl -d /dev/media0 -V '"43c60000.mipi_csi2_rx_subsystem":0 [fmt:UYVY/'1920x1080' field:none]'
*/
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <iostream>
#include <fstream>
#include <linux/videodev2.h>
#include <cstdlib>
// #include "opencv2/opencv.hpp"
#define FMT_NUM_PLANES 3
#define WIDTH 640
#define HEIGHT 480
struct buffer_addr_struct{
void *start[FMT_NUM_PLANES];
size_t length[FMT_NUM_PLANES];
} *buffers;
static int xioctl(int fd, int request, void *arg){
int r;
do {
r = ioctl (fd, request, arg);
if (request == VIDIOC_DQBUF) {
std::cout << "r : " << r << std::endl;
}
} while (-1 == r && EINTR == errno);
return r;
}
int main() {
unsigned char *buffer;
// 1. Open Video Device.
int fd;
fd = open("/dev/video0", O_RDWR, 0);
if (fd == -1){
std::cout << "Failed to open video device." << std::endl;
return 1;
}
// 2. Querying video capabilities.
struct v4l2_capability caps;
memset(&caps, 0, sizeof(caps));
if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &caps)){
std::cout << "Failed to query capabilities." << std::endl;
return 1;
}
std::cout << "bus_info : " << caps.bus_info << std::endl;
std::cout << "card : " << caps.card << std::endl;
std::cout << "driver : " << caps.driver << std::endl;
std::cout << "version : " << caps.version << std::endl;
// 3. Format Specification.
{
struct v4l2_format fmt;
memset(&(fmt), 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
fmt.fmt.pix_mp.width = WIDTH;
fmt.fmt.pix_mp.height = HEIGHT;
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt)){
std::cout << "Failed to set pixel format." << std::endl;
return 1;
}
}
int num_planes;
struct v4l2_requestbuffers reqbuf;
const int MAX_BUF_COUNT = 3;/*we want at least 3 buffers*/
// 4. Request Buffer
{
memset(&(reqbuf), 0, sizeof(reqbuf));
reqbuf.count = FMT_NUM_PLANES;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
reqbuf.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &reqbuf)){
std::cout << "Failed to request buffer." << std::endl;
return 1;
}
if (reqbuf.count < MAX_BUF_COUNT){
std::cout << "Not enought buffer memory." << std::endl;
return 1;
}
std::cout << "reqbuf.count : " << reqbuf.count << std::endl;
buffers = (buffer_addr_struct*) calloc(reqbuf.count, sizeof(*buffers));
// assert(buffers != NULL);
}
// 5. Query Buffer
{
for(int i = 0; i < reqbuf.count; i++){
struct v4l2_plane planes[FMT_NUM_PLANES];
struct v4l2_buffer buf;
memset(&(buf), 0, sizeof(buf));
memset(planes, 0, sizeof(planes));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
buf.memory = V4L2_MEMORY_MMAP;
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
buf.index = i;
if(-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf)){
std::cout << "Failed to query buffer." << std::endl;
return 1;
}
num_planes = buf.length;
std::cout << "buf.length : " << buf.length << std::endl;
std::cout << "buf.m.offset : " << buf.m.offset << std::endl;
for(int j = 0; j < num_planes; j++){
buffers[i].length[j] = buf.m.planes[j].length;
std::cout << "buf.m.planes[j].length : " << buf.m.planes[j].length << std::endl;
buffers[i].start[j] = mmap(NULL, buf.m.planes[j].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.planes[j].m.mem_offset);
if(MAP_FAILED == buffers[i].start[j]){
std::cout << "mmap error" << std::endl;
}
std::cout << "buffers[i].start[j] : " << buffers[i].start[j] << std::endl;
}
}
}
//5.5
{
for (int i = 0; i < reqbuf.count; ++i) {
struct v4l2_buffer buf;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
struct v4l2_plane planes[FMT_NUM_PLANES];
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
std::cout << "unko " << std::endl;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
std::cerr << "VIDIOC_QBUF" << std::endl;
}
}
// 6. Start Streaming
{
struct v4l2_buffer buf;
memset(&(buf), 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
if(-1 == xioctl(fd, VIDIOC_STREAMON, &buf.type))
{
std::cout << "Fail to start Capture" << std::endl;
return 1;
}
std::cout << "start streaming" << std::endl;
}
char camdata[WIDTH*HEIGHT*2];
//cv::namedWindow("edges",1);
// cv::Mat bayerRaw(HEIGHT, WIDTH, CV_8UC1);
// cv::Mat color(HEIGHT, 1, CV_8UC3);
struct v4l2_buffer buf;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;//V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
// buf.index = 0;
struct v4l2_plane planes[FMT_NUM_PLANES];
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
while (true) {
// 7. Capture Image
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
struct timeval tv = {0};
tv.tv_sec = 2;
int r = select(fd+1, &fds, NULL, NULL, &tv);
if(-1 == r){
std::cout << "Waiting for Frame" << std::endl;
return 1;
}
if(-1 == xioctl(fd, VIDIOC_DQBUF, &buf)){
std::cout << "Retrieving Frame" << std::endl;
return 1;
}
std::cout << buf.index << std::endl;
// Connect buffer to queue for next capture.
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) {
std::cout << "VIDIOC_QBUF" << std::endl;
}
}
// 8. Store Image in OpenCV Data Type
{
for(int j = 0; j < num_planes; j++){
memcpy(camdata, buffers[buf.index].start[j], WIDTH*HEIGHT*2);
}
//memcpy(bayerRaw.data, buffer, WIDTH * HEIGHT);
//cv::cvtColor(bayerRaw, color, CV_BayerGB2BGR);
}
// 9. Display Image
{
// FILE* fp = fopen("./camdata.dat", "wb");
// fwrite(camdata, sizeof(camdata), 1, fp);
// fclose(fp);
//cv::imwrite("./image.jpg", color);
//cv::imshow("edges", color);
/*if (-1 != cv::waitKey(1000)) {
break;
}*/
}
}
// 10. Turn off streaming.
if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &buf.type)) {
std::cout << "VIDIOC_STREAMOFF" << std::endl;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.