"Fossies" - the Fresh Open Source Software Archive

Member "motion-Release-4.3.0/src/video_loopback.c" (14 Jan 2020, 7980 Bytes) of package /linux/misc/motion-Release-4.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "video_loopback.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  *    video_loopback.c
    3  *
    4  *    Video loopback functions for motion.
    5  *    Copyright 2000 by Jeroen Vreeken (pe1rxq@amsat.org)
    6  *    Copyright 2008 by Angel Carpintero (motiondevelop@gmail.com)
    7  *    This software is distributed under the GNU public license version 2
    8  *    See also the file 'COPYING'.
    9  *
   10  */
   11 #include "translate.h"
   12 #include "motion.h"
   13 
   14 #if (defined(HAVE_V4L2)) && (!defined(BSD))
   15 
   16 #include "video_loopback.h"
   17 #include <dirent.h>
   18 #include <sys/ioctl.h>
   19 #include <linux/videodev2.h>
   20 
   21 static int vlp_open_vidpipe(void)
   22 {
   23     int pipe_fd = -1;
   24     char pipepath[255];
   25     char buffer[255];
   26     DIR *dir;
   27     struct dirent *dirp;
   28     const char prefix[] = "/sys/class/video4linux/";
   29     int fd,tfd;
   30     int len,min;
   31     int retcd;
   32 
   33     if ((dir = opendir(prefix)) == NULL) {
   34         MOTION_LOG(CRT, TYPE_VIDEO, SHOW_ERRNO,_("Failed to open '%s'"), prefix);
   35         return -1;
   36     }
   37 
   38     while ((dirp = readdir(dir)) != NULL) {
   39         if (!strncmp(dirp->d_name, "video", 5)) {
   40 
   41             retcd = snprintf(buffer, sizeof(buffer),"%s%s/name", prefix, dirp->d_name);
   42             if ((retcd<0) || (retcd >= (int)sizeof(buffer))) {
   43                 MOTION_LOG(NTC, TYPE_VIDEO, SHOW_ERRNO
   44                     ,_("Error specifying buffer: %s"),buffer);
   45                 continue;
   46             } else {
   47                 MOTION_LOG(NTC, TYPE_VIDEO, SHOW_ERRNO,_("Opening buffer: %s"),buffer);
   48             }
   49 
   50             if ((fd = open(buffer, O_RDONLY|O_CLOEXEC)) >= 0) {
   51                 if ((len = read(fd, buffer, sizeof(buffer)-1)) < 0) {
   52                     close(fd);
   53                     continue;
   54                 }
   55                 buffer[len]=0;
   56                 MOTION_LOG(NTC, TYPE_VIDEO, SHOW_ERRNO,_("Read buffer: %s"),buffer);
   57                 if (strncmp(buffer, "Loopback video device",21)) { /* weird stuff after minor */
   58                     close(fd);
   59                     continue;
   60                 }
   61                 min = atoi(&buffer[21]);
   62 
   63                 retcd = snprintf(buffer,sizeof(buffer),"/dev/%s",dirp->d_name);
   64                 if ((retcd < 0) || (retcd >= (int)sizeof(buffer))) {
   65                     MOTION_LOG(NTC, TYPE_VIDEO, SHOW_ERRNO
   66                         ,_("Error specifying buffer: %s"),buffer);
   67                     close(fd);
   68                     continue;
   69                 } else {
   70                     MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("found video device '%s' %d"), buffer,min);
   71                 }
   72 
   73                 if ((tfd = open(buffer, O_RDWR|O_CLOEXEC)) >= 0) {
   74                     strncpy(pipepath, buffer, sizeof(pipepath));
   75                     if (pipe_fd >= 0) close(pipe_fd);
   76                     pipe_fd = tfd;
   77                     break;
   78                 }
   79             }
   80                 close(fd);
   81         }
   82     }
   83 
   84     closedir(dir);
   85 
   86     if (pipe_fd >= 0)
   87       MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opened %s as pipe output"), pipepath);
   88 
   89     return pipe_fd;
   90 }
   91 
   92 typedef struct capent {const char *cap; int code;} capentT;
   93     capentT cap_list[] ={
   94         {"V4L2_CAP_VIDEO_CAPTURE"        ,0x00000001 },
   95         {"V4L2_CAP_VIDEO_CAPTURE_MPLANE" ,0x00001000 },
   96         {"V4L2_CAP_VIDEO_OUTPUT"         ,0x00000002 },
   97         {"V4L2_CAP_VIDEO_OUTPUT_MPLANE"  ,0x00002000 },
   98         {"V4L2_CAP_VIDEO_M2M"            ,0x00004000 },
   99         {"V4L2_CAP_VIDEO_M2M_MPLANE"     ,0x00008000 },
  100         {"V4L2_CAP_VIDEO_OVERLAY"        ,0x00000004 },
  101         {"V4L2_CAP_VBI_CAPTURE"          ,0x00000010 },
  102         {"V4L2_CAP_VBI_OUTPUT"           ,0x00000020 },
  103         {"V4L2_CAP_SLICED_VBI_CAPTURE"   ,0x00000040 },
  104         {"V4L2_CAP_SLICED_VBI_OUTPUT"    ,0x00000080 },
  105         {"V4L2_CAP_RDS_CAPTURE"          ,0x00000100 },
  106         {"V4L2_CAP_VIDEO_OUTPUT_OVERLAY" ,0x00000200 },
  107         {"V4L2_CAP_HW_FREQ_SEEK"         ,0x00000400 },
  108         {"V4L2_CAP_RDS_OUTPUT"           ,0x00000800 },
  109         {"V4L2_CAP_TUNER"                ,0x00010000 },
  110         {"V4L2_CAP_AUDIO"                ,0x00020000 },
  111         {"V4L2_CAP_RADIO"                ,0x00040000 },
  112         {"V4L2_CAP_MODULATOR"            ,0x00080000 },
  113         {"V4L2_CAP_SDR_CAPTURE"          ,0x00100000 },
  114         {"V4L2_CAP_EXT_PIX_FORMAT"       ,0x00200000 },
  115         {"V4L2_CAP_SDR_OUTPUT"           ,0x00400000 },
  116         {"V4L2_CAP_READWRITE"            ,0x01000000 },
  117         {"V4L2_CAP_ASYNCIO"              ,0x02000000 },
  118         {"V4L2_CAP_STREAMING"            ,0x04000000 },
  119         {"V4L2_CAP_DEVICE_CAPS"          ,0x80000000 },
  120         {"Last",0}
  121 };
  122 
  123 static void vlp_show_vcap(struct v4l2_capability *cap) {
  124     unsigned int vers = cap->version;
  125     unsigned int c    = cap->capabilities;
  126     int i;
  127 
  128     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "Pipe Device");
  129     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "cap.driver:   %s",cap->driver);
  130     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "cap.card:     %s",cap->card);
  131     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "cap.bus_info: %s",cap->bus_info);
  132     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "cap.card:     %u.%u.%u",(vers >> 16) & 0xFF,(vers >> 8) & 0xFF,vers & 0xFF);
  133     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "Device capabilities");
  134     for (i=0;cap_list[i].code;i++)
  135         if (c & cap_list[i].code)
  136             MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "%s",cap_list[i].cap);
  137     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "------------------------");
  138 }
  139 
  140 static void vlp_show_vfmt(struct v4l2_format *v) {
  141     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "type: type:           %d",v->type);
  142     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "fmt.pix.width:        %d",v->fmt.pix.width);
  143     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "fmt.pix.height:       %d",v->fmt.pix.height);
  144     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "fmt.pix.pixelformat:  %d",v->fmt.pix.pixelformat);
  145     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "fmt.pix.sizeimage:    %d",v->fmt.pix.sizeimage);
  146     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "fmt.pix.field:        %d",v->fmt.pix.field);
  147     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "fmt.pix.bytesperline: %d",v->fmt.pix.bytesperline);
  148     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "fmt.pix.colorspace:   %d",v->fmt.pix.colorspace);
  149     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO, "------------------------");
  150 }
  151 
  152 int vlp_startpipe(const char *dev_name, int width, int height)
  153 {
  154     int dev;
  155     struct v4l2_format v;
  156     struct v4l2_capability vc;
  157 
  158     if (!strcmp(dev_name, "-")) {
  159         dev = vlp_open_vidpipe();
  160     } else {
  161         dev = open(dev_name, O_RDWR|O_CLOEXEC);
  162         MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opened %s as pipe output"), dev_name);
  163     }
  164 
  165     if (dev < 0) {
  166         MOTION_LOG(ERR, TYPE_VIDEO, SHOW_ERRNO,_("Opening %s as pipe output failed"), dev_name);
  167         return -1;
  168     }
  169 
  170 
  171     if (ioctl(dev, VIDIOC_QUERYCAP, &vc) == -1) {
  172         MOTION_LOG(ERR, TYPE_VIDEO, SHOW_ERRNO, "ioctl (VIDIOC_QUERYCAP)");
  173         return -1;
  174     }
  175 
  176     vlp_show_vcap(&vc);
  177 
  178     memset(&v, 0, sizeof(v));
  179 
  180     v.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
  181 
  182     if (ioctl(dev, VIDIOC_G_FMT, &v) == -1) {
  183         MOTION_LOG(ERR, TYPE_VIDEO, SHOW_ERRNO, "ioctl (VIDIOC_G_FMT)");
  184         return -1;
  185     }
  186     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO,_("Original pipe specifications"));
  187     vlp_show_vfmt(&v);
  188 
  189     v.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
  190     v.fmt.pix.width = width;
  191     v.fmt.pix.height = height;
  192     v.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
  193     v.fmt.pix.sizeimage = 3 * width * height / 2;
  194     v.fmt.pix.bytesperline = width;
  195     v.fmt.pix.field = V4L2_FIELD_NONE;
  196     v.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
  197     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO,_("Proposed pipe specifications"));
  198     vlp_show_vfmt(&v);
  199 
  200     if (ioctl(dev,VIDIOC_S_FMT, &v) == -1) {
  201         MOTION_LOG(ERR, TYPE_VIDEO, SHOW_ERRNO, "ioctl (VIDIOC_S_FMT)");
  202         return -1;
  203     }
  204 
  205     MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO,_("Final pipe specifications"));
  206     vlp_show_vfmt(&v);
  207 
  208     return dev;
  209 }
  210 
  211 int vlp_putpipe(int dev, unsigned char *image, int imgsize)
  212 {
  213     return write(dev, image, imgsize);
  214 }
  215 
  216 
  217 #endif /* HAVE_V4L2 && !BSD */