рд▓рд┐рдирдХреНрд╕ рдореЗрдВ usb рдХреИрдордХреЙрд░реНрдбрд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВред рднрд╛рдЧ реи

рдЕрднрд┐рд╡рд╛рджрди, рд╣рдмреНрд░!

рд╣рдо рд▓рд┐рдирдХреНрд╕ рдореЗрдВ рдХреИрдордХреЙрд░реНрдбрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдкрд░ рд▓реЗрдЦреЛрдВ рдХреА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВред рдкрд╣рд▓реЗ рднрд╛рдЧ [1] рдореЗрдВ , рд╣рдордиреЗ рд╡реАрдбрд┐рдпреЛ рдбрд┐рд╡рд╛рдЗрд╕ рдХреЗ рдкреНрд░рд╛рдердорд┐рдХ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдЦреЛрд▓рдиреЗ рдФрд░ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рддрдВрддреНрд░ рдХреА рдЬрд╛рдВрдЪ рдХреАред рдПрдХ рд╕рд░рд▓ catvd рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд▓рд┐рдЦреА рдЧрдИ рдереАред рдЖрдЬ рд╣рдо рдЕрдкрдиреЗ рдЫреЛрдЯреЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░реЗрдВрдЧреЗ , рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ рдЖрдкрдХреЛ ioctl рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╡рд░рдг рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ред
Xioctl рд╡рд┐рдзрд┐ рдХреЛрдб
int videodevice::xioctl(int fd, int request, void *arg) { int r; r = ioctl (fd, request, arg); if(r == -1) { if (errno == EAGAIN) return EAGAIN; stringstream ss; ss << "ioctl code " << request << " "; errno_exit(ss.str()); } return r; } 


рдпрджрд┐ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдереА рдФрд░ рдХреЛрдИ рд╕рдВрджреЗрд╢ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рддреЛ рдпрд╣ рдЖрд╡рд░рдг рдЖрдкрдХреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рдЖрдЗрдП рдХреИрдорд░реЗ рд╕реЗ рдЪрд┐рддреНрд░ рдХреЛ рдкрдврд╝рдиреЗ рдФрд░ рдЗрд╕реЗ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рд╣реЗрдЬрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред
GetFrame рд╡рд┐рдзрд┐ рдХреЛрдб
 void videodevice::getFrame(string file_name) { initMMAP(); startCapturing(); long int i = 0; for (;;) { if(readFrame(file_name)) break; i++; } cout << "iter == " << i << endl; stopCapturing(); freeMMAP(); } 


readFrame рд╡рд┐рдзрд┐ - рдкреНрд░рд╛рдкреНрдд рдЫрд╡рд┐ рдХреЛ рдкрдврд╝рдиреЗ рдФрд░ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ред
initMMAP (), freeMMAP () - рдЙрдкрдХрд░рдг рдореЗрдореЛрд░реА рдмрдлрд░ рдмрдирд╛рдиреЗ / рд╕рд╛рдлрд╝ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗред
рддрд░реАрдХреЗ рд╢реБрд░реВ (), stopCapturing () - рд╡реАрдбрд┐рдпреЛ рдбрд┐рд╡рд╛рдЗрд╕ рдХреЗ рд╕реНрдЯреНрд░реАрдорд┐рдВрдЧ рдореЛрдб рдХреЛ рд╕рдХреНрд╖рдо / рдЕрдХреНрд╖рдо рдХрд░реЗрдВред рдХреИрдорд░реЗ рдкрд░ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЛ рдзреНрд╡рдЬ V4L2_CAP_STREAMING [*] рд╕реЗ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдЖрдЗрдП inMMAP рд╡рд┐рдзрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВ
InitMMAP рд╡рд┐рдзрд┐ рдХреЛрдб
 void videodevice::initMMAP() { struct v4l2_requestbuffers req; req.count = 1; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; xioctl(fd, VIDIOC_REQBUFS, &req); devbuffer = (buffer*) calloc(req.count, sizeof(*devbuffer)); struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = 0; xioctl(fd, VIDIOC_QUERYBUF, &buf); devbuffer->length = buf.length; devbuffer->start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); if (devbuffer->start == MAP_FAILED) errno_exit("mmap"); } 


рдлрд╝рдВрдХреНрд╢рди VIDIOC_REQBUFS [ _ ] рдбрд┐рд╡рд╛рдЗрд╕ рдХреЗ рдЕрдВрджрд░ рдореЗрдореЛрд░реА рдмрдлрд░ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред V4l2_requestbuffers рд╕рдВрд░рдЪрдирд╛ рдЖрд░рдВрднреАрдХрд░рдг рдкреИрд░рд╛рдореАрдЯрд░ рд╕реЗрдЯ рдХрд░рддреА рд╣реИ
 struct v4l2_requestbuffers { __u32 count; //  __u32 type; //    __u32 memory; //   . __u32 reserved[2]; //   }; 

рдмрдлрд░ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЗрд╕реЗ рдореЗрдореЛрд░реА рдПрд░рд┐рдпрд╛ (рдореИрдкрд┐рдВрдЧ) рдкрд░ рдореИрдк рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдлрд╝рдВрдХреНрд╢рди VIDIOC_QUERYBUF [ allows ] рдЖрдкрдХреЛ рдмрдлрд░ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдкрдврд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдореЗрдореЛрд░реА-рдореИрдкрд┐рдВрдЧ рдХреНрд╖реЗрддреНрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред V4l2_buffer рдХреА рд╕рдВрд░рдЪрдирд╛ рдмрдбрд╝реА рд╣реИ, рдореИрдВ рдЖрд╡рд╢реНрдпрдХ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реВрдВрдЧрд╛:
 struct v4l2_buffer { //  VIDIOC_QUERYBUF    __u32 index; //     ( v4l2_requestbuffers.cout > 1) __u32 type; //  (   v4l2_requestbuffers.type) //  VIDIOC_QUERYBUF        memory-mapping union { __u32 offset; //       } m; __u32 length; //   }; 

рд╕рд┐рд╕реНрдЯрдо рдлрд╝рдВрдХреНрд╢рди mmap () [3] рдЖрдкрдХреЛ рд░реИрдо рдореЗрдВ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдпрд╛ рдбрд┐рд╡рд╛рдЗрд╕ рдореЗрдореЛрд░реА рдХреНрд╖реЗрддреНрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред Mmap () рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХрдиреЗрдХреНрдЯ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП
 <sys/mman.h> 

рдЕрдЧрд▓рд╛, рдЖрдкрдХреЛ рдХреИрдорд░реЗ рдХреЛ рдХреИрдкреНрдЪрд░ рдореЛрдб рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
StartCapturing рд╡рд┐рдзрд┐ рдХреЛрдб
 void videodevice::startCapturing() { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = 0; xioctl(fd, VIDIOC_QBUF, &buf); enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; xioctl(fd, VIDIOC_STREAMON, &type); } 


рдлрд╝рдВрдХреНрд╢рди VIDIOC_QBUF [ puts ] рдбрд┐рд╡рд╛рдЗрд╕ рдбреНрд░рд╛рдЗрд╡рд░ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХрддрд╛рд░ рдореЗрдВ рдмрдлрд░ рдбрд╛рд▓рддрд╛ рд╣реИред рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдлрд╝реАрд▓реНрдб VIDIOC_REQBUFS рдпрд╛ VIDIOC_QUERYBUF рдХреЗ рд╕рдорд╛рди рд╣реИрдВред
VIDIOC_STREAMON [ _ ] рдлрд╝рдВрдХреНрд╢рди рдХреИрдорд░реЗ рдХреЛ рдореЛрдб рдХреИрдкреНрдЪрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рд┐рдЪ рдХрд░рддрд╛ рд╣реИред

рдЕрдм рдХреИрдорд░рд╛ рдЪрд╛рд▓реВ рд╣реИ рдФрд░ рдЫрд╡рд┐рдпреЛрдВ рдХреЛ рдХреИрдкреНрдЪрд░ рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рддрд╕реНрд╡реАрд░ рдЕрднреА рднреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
ReadFrame рд╡рд┐рдзрд┐ рдХреЛрдб
 int videodevice::readFrame(string file_name) { struct v4l2_buffer buf; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (xioctl(fd, VIDIOC_DQBUF, &buf) == EAGAIN) return 0; buffer *temp = devbuffer; FILE *out_file = fopen(file_name.c_str(),"w"); fwrite(temp->start,temp->length,1,out_file); fclose(out_file); return 1; } 


VIDIOC_DQBUF [ function ] рдлрд╝рдВрдХреНрд╢рди рдмрдлрд░ рдХреЛ рдбреНрд░рд╛рдЗрд╡рд░ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХрддрд╛рд░ рд╕реЗ рдореБрдХреНрдд рдХрд░рддрд╛ рд╣реИред рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╣рдореЗрдВ EAGAIN рддреНрд░реБрдЯрд┐ рдорд┐рд▓ рд╕рдХрддреА рд╣реИред рдЗрд╕рдореЗрдВ рдХреБрдЫ рднреА рдЦрддрд░рдирд╛рдХ рдирд╣реАрдВ рд╣реИ; рдЖрдкрдХреЛ рдлрд┐рд░ рд╕реЗ VIDIOC_DQBUF рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдбреНрд░рд╛рдЗрд╡рд░ рдЕрднреА рднреА рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░ рд░рд╣рд╛ рд╣реИ рдФрд░ рдХрддрд╛рд░ рд╕реЗ рдмрдлрд░ рдХреЛ рдЬрд╛рд░реА рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рдлрд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде, рд╣рдореЗрдВ рдЕрдкрдиреА рддрд╕реНрд╡реАрд░ рд╣рд╛рдереЛрдВ рдореЗрдВ рдорд┐рд▓рддреА рд╣реИред рд▓реЗрдЦ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ, рдХреЛрдб рдореЗрдВ рдПрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛ред рдПрдХ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдЖрдкрдХреЛ рдпрд╣ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдХрд┐ VIDIOC_DQBUF рдХреЗ рд╕рдлрд▓ рд╣реЛрдиреЗ рддрдХ рдХрд┐рддрдиреЗ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдПрдХ рдирд┐рд╖реНрдХреНрд░рд┐рдп рд▓реВрдк рд╕реЗ рдЧреБрдЬрд░рддреЗ рд╣реИрдВред

рд╕рдВрдХрд▓рди
 $ cmake . $ make 


рдХрд╛рд░реНрдпрдХреНрд░рдо рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИред
 $./getimage Open device /dev/video0 Init mmap Start capturing read frame from buffer and write to file iter == 831013 stop Capturing free mmap Close device /dev/video0 

"Iter == 831013" рд╕реЗ рдпрд╣ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рддрд╕реНрд╡реАрд░ рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдП рдмрдлрд░ рдореЗрдВ рдЧрд┐рд░рддреА рд╣реИред рддреЗрдЬреА рд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдХрдИ рдмрдлрд╝рд░реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкрд╣рд▓реЗ рдореБрдлрд╝реНрдд рдЖрджрд┐ рд╕реЗ рддрд╕реНрд╡реАрд░ рдЦреАрдВрдЪ рд╕рдХрддреЗ рд╣реИрдВред

рдЖрдЬ рдореЗрдореЛрд░реА рдмрдлрд░ рдХреЗ рдЖрд░рдВрдн рдФрд░ рдЙрд╕рд╕реЗ рдЪрд┐рддреНрд░ рдкрдврд╝рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ред рдЫрд╡рд┐ рдХреЛ рдХрдЪреНрдЪреЗ рд╕реНрд╡рд░реВрдк рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЧрдпрд╛ рд╣реИред рдЖрдк рд╢реЛрдЯрд╡реЗрд▓ рдХрд╛рд░реНрдпрдХреНрд░рдо рдЦреЛрд▓ рд╕рдХрддреЗ рд╣реИрдВред рдЕрдЧрд▓реЗ рд▓реЗрдЦ рдореЗрдВ, рдЫрд╡рд┐ рдХреЗ рдмрдирд╛рд╡рдЯ (рдПрд╕рдбреАрдПрд▓ 2 рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ) рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдХреБрдЫ рдЫрд╡рд┐ рдкреНрд░рд╛рд░реВрдк рдФрд░ рдХреИрдорд░рд╛ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдкреНрд░рднрд╛рд╡рд┐рдд рд╣реЛрдВрдЧреЗред

рд▓реЗрдЦ рдореЗрдВ рдкреНрд░рдпреБрдХреНрдд рд╕рдВрд╕рд╛рдзрди:
  1. рд▓рд┐рдирдХреНрд╕ рдореЗрдВ usb рдХреИрдордХреЙрд░реНрдбрд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВред рднрд╛рдЧ 1
  2. рд▓рд┐рдирдХреНрд╕ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП рд╡реАрдбрд┐рдпреЛ
  3. mmap рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдФрд░ рдЕрдзрд┐рдХ ()

рдкреНрд░рдпреБрдХреНрдд рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдВрдХ:

рд╕реНрд░реЛрдд рдХреЛрдб

Source: https://habr.com/ru/post/In212531/


All Articles