Advertisement
Guest User

webcam frame in Linux

a guest
Oct 15th, 2019
718
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.89 KB | None | 0 0
  1. // original file : https://gist.github.com/mike168m/6dd4eb42b2ec906e064d
  2. // patch by abureau le 15/10/19
  3. #include <iostream>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <linux/ioctl.h>
  7. #include <linux/types.h>
  8. #include <linux/v4l2-common.h>
  9. #include <linux/v4l2-controls.h>
  10. #include <linux/videodev2.h>
  11. #include <fcntl.h>
  12. #include <unistd.h>
  13. #include <sys/ioctl.h>
  14. #include <sys/mman.h>
  15. #include <string.h>
  16. #include <fstream>
  17. #include <string>
  18.  
  19. using namespace std;
  20.  
  21. int main() {
  22.     // 1.  Open the device
  23.     int fd; // A file descriptor to the video device
  24.     fd = open("/dev/video0",O_RDWR);
  25.     if(fd < 0){
  26.         perror("Failed to open device, OPEN");
  27.         return 1;
  28.     }
  29.  
  30.  
  31.     // 2. Ask the device if it can capture frames
  32.     v4l2_capability capability;
  33.     if(ioctl(fd, VIDIOC_QUERYCAP, &capability) < 0){
  34.         // something went wrong... exit
  35.         perror("Failed to get device capabilities, VIDIOC_QUERYCAP");
  36.         return 1;
  37.     }
  38.  
  39.  
  40.     // 3. Set Image format
  41.     v4l2_format imageFormat;
  42.     imageFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  43.     imageFormat.fmt.pix.width = 640;
  44.     imageFormat.fmt.pix.height = 480;
  45.     imageFormat.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
  46.     imageFormat.fmt.pix.field = V4L2_FIELD_NONE;
  47.     // tell the device you are using this format
  48.     if(ioctl(fd, VIDIOC_S_FMT, &imageFormat) < 0){
  49.         perror("Device could not set format, VIDIOC_S_FMT");
  50.         return 1;
  51.     }
  52.  
  53.  
  54.     // 4. Request Buffers from the device
  55.     v4l2_requestbuffers requestBuffer = {0};
  56.     requestBuffer.count = 1; // one request buffer
  57.     requestBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // request a buffer wich we an use for capturing frames
  58.     requestBuffer.memory = V4L2_MEMORY_MMAP;
  59.  
  60.     if(ioctl(fd, VIDIOC_REQBUFS, &requestBuffer) < 0){
  61.         perror("Could not request buffer from device, VIDIOC_REQBUFS");
  62.         return 1;
  63.     }
  64.  
  65.  
  66.     // 5. Quety the buffer to get raw data ie. ask for the you requested buffer
  67.     // and allocate memory for it
  68.     v4l2_buffer queryBuffer = {0};
  69.     queryBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  70.     queryBuffer.memory = V4L2_MEMORY_MMAP;
  71.     queryBuffer.index = 0;
  72.     if(ioctl(fd, VIDIOC_QUERYBUF, &queryBuffer) < 0){
  73.         perror("Device did not return the buffer information, VIDIOC_QUERYBUF");
  74.         return 1;
  75.     }
  76.     // use a pointer to point to the newly created buffer
  77.     // mmap() will map the memory address of the device to
  78.     // an address in memory
  79.     char* buffer = (char*)mmap(NULL, queryBuffer.length, PROT_READ | PROT_WRITE, MAP_SHARED,
  80.                         fd, queryBuffer.m.offset);
  81.     memset(buffer, 0, queryBuffer.length);
  82.  
  83.  
  84.     // 6. Get a frame
  85.     // Create a new buffer type so the device knows whichbuffer we are talking about
  86.     v4l2_buffer bufferinfo;
  87.     memset(&bufferinfo, 0, sizeof(bufferinfo));
  88.     bufferinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  89.     bufferinfo.memory = V4L2_MEMORY_MMAP;
  90.     bufferinfo.index = 0;
  91.  
  92.     // Activate streaming
  93.     int type = bufferinfo.type;
  94.     if(ioctl(fd, VIDIOC_STREAMON, &type) < 0){
  95.         perror("Could not start streaming, VIDIOC_STREAMON");
  96.         return 1;
  97.     }
  98.  
  99. /***************************** Begin looping here *********************/
  100.     // Queue the buffer
  101.     if(ioctl(fd, VIDIOC_QBUF, &bufferinfo) < 0){
  102.         perror("Could not queue buffer, VIDIOC_QBUF");
  103.         return 1;
  104.     }
  105.  
  106.     // Dequeue the buffer
  107.     if(ioctl(fd, VIDIOC_DQBUF, &bufferinfo) < 0){
  108.         perror("Could not dequeue the buffer, VIDIOC_DQBUF");
  109.         return 1;
  110.     }
  111.     // Frames get written after dequeuing the buffer
  112.  
  113.     cout << "Buffer has: " << (double)bufferinfo.bytesused / 1024
  114.             << " KBytes of data" << endl;
  115.  
  116.     // Write the data out to file
  117.     ofstream outFile;
  118.     outFile.open("webcam_output.jpeg", ios::binary| ios::app);
  119.  
  120.     int bufPos = 0, outFileMemBlockSize = 0;  // the position in the buffer and the amoun to copy from
  121.                                         // the buffer
  122.     int remainingBufferSize = bufferinfo.bytesused; // the remaining buffer size, is decremented by
  123.                                                     // memBlockSize amount on each loop so we do not overwrite the buffer
  124.     char* outFileMemBlock = NULL;  // a pointer to a new memory block
  125.     int itr = 0; // counts thenumber of iterations
  126.     while(remainingBufferSize > 0) {
  127.         bufPos += outFileMemBlockSize;  // increment the buffer pointer on each loop
  128.                                         // initialise bufPos before outFileMemBlockSize so we can start
  129.                                         // at the begining of the buffer
  130.  
  131.         outFileMemBlockSize = 1024;    // set the output block size to a preferable size. 1024 :)
  132.         outFileMemBlock = new char[sizeof(char) * outFileMemBlockSize];
  133.  
  134.         // copy 1024 bytes of data starting from buffer+bufPos
  135.         memcpy(outFileMemBlock, buffer+bufPos, outFileMemBlockSize);
  136.         outFile.write(outFileMemBlock,outFileMemBlockSize);
  137.  
  138.         // calculate the amount of memory left to read
  139.         // if the memory block size is greater than the remaining
  140.         // amount of data we have to copy
  141.         if(outFileMemBlockSize > remainingBufferSize)
  142.             outFileMemBlockSize = remainingBufferSize;
  143.  
  144.         // subtract the amount of data we have to copy
  145.         // from the remaining buffer size
  146.         remainingBufferSize -= outFileMemBlockSize;
  147.  
  148.         // display the remaining buffer size
  149.         cout << itr++ << " Remaining bytes: "<< remainingBufferSize << endl;
  150.         delete outFileMemBlock;
  151.     }
  152.  
  153.     // Close the file
  154.     outFile.close();
  155.  
  156.  
  157. /******************************** end looping here **********************/
  158.  
  159.     // end streaming
  160.     if(ioctl(fd, VIDIOC_STREAMOFF, &type) < 0){
  161.         perror("Could not end streaming, VIDIOC_STREAMOFF");
  162.         return 1;
  163.     }
  164.  
  165.     close(fd);
  166.     return 0;
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement