LCOV - code coverage report
Current view: top level - src/media/video/v4l2 - video_device_impl.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 71 258 27.5 %
Date: 2024-12-21 08:56:24 Functions: 16 30 53.3 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2024 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  This program is free software: you can redistribute it and/or modify
       5             :  *  it under the terms of the GNU General Public License as published by
       6             :  *  the Free Software Foundation, either version 3 of the License, or
       7             :  *  (at your option) any later version.
       8             :  *
       9             :  *  This program is distributed in the hope that it will be useful,
      10             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12             :  *  GNU General Public License for more details.
      13             :  *
      14             :  *  You should have received a copy of the GNU General Public License
      15             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include <algorithm>
      19             : #include <cassert>
      20             : #include <climits>
      21             : #include <cstring>
      22             : #include <map>
      23             : #include <sstream>
      24             : #include <stdexcept>
      25             : #include <string>
      26             : #include <vector>
      27             : 
      28             : extern "C" {
      29             : #include <linux/videodev2.h>
      30             : #if !defined(VIDIOC_ENUM_FRAMESIZES) || !defined(VIDIOC_ENUM_FRAMEINTERVALS)
      31             : #error You need at least Linux 2.6.19
      32             : #endif
      33             : 
      34             : #include <fcntl.h>
      35             : #include <unistd.h>
      36             : #include <sys/ioctl.h>
      37             : }
      38             : 
      39             : #include "logger.h"
      40             : #include "../video_device.h"
      41             : #include "string_utils.h"
      42             : 
      43             : #define ZEROVAR(x) std::memset(&(x), 0, sizeof(x))
      44             : 
      45             : namespace jami {
      46             : namespace video {
      47             : 
      48             : class VideoV4l2Rate
      49             : {
      50             : public:
      51          38 :     VideoV4l2Rate(unsigned rate_numerator = 0, unsigned rate_denominator = 0, unsigned format = 0)
      52          38 :         : frame_rate(rate_denominator, rate_numerator)
      53          38 :         , pixel_format(format)
      54          38 :     {}
      55             : 
      56             :     FrameRate frame_rate;
      57             :     unsigned pixel_format;
      58             :     std::string libAvPixelformat() const;
      59             : };
      60             : 
      61             : class VideoV4l2Size
      62             : {
      63             : public:
      64          38 :     VideoV4l2Size(const unsigned width, const unsigned height)
      65          38 :         : width(width)
      66          38 :         , height(height)
      67          38 :         , rates_()
      68          38 :     {}
      69             : 
      70             :     /**
      71             :      * @throw std::runtime_error
      72             :      */
      73             :     void readFrameRates(int fd, unsigned int pixel_format);
      74             : 
      75             :     std::vector<FrameRate> getRateList() const;
      76             :     VideoV4l2Rate getRate(const FrameRate& rate) const;
      77             : 
      78             :     unsigned width;
      79             :     unsigned height;
      80             : 
      81             : private:
      82             :     void addRate(VideoV4l2Rate proposed_rate);
      83             :     std::vector<VideoV4l2Rate> rates_;
      84             : };
      85             : 
      86             : bool
      87           0 : operator==(VideoV4l2Size& a, VideoV4l2Size& b)
      88             : {
      89           0 :     return a.height == b.height && a.width == b.width;
      90             : }
      91             : 
      92             : class VideoV4l2Channel
      93             : {
      94             : public:
      95             :     VideoV4l2Channel(unsigned idx, const char* s);
      96             : 
      97             :     /**
      98             :      * @throw std::runtime_error
      99             :      */
     100             :     void readFormats(int fd);
     101             : 
     102             :     /**
     103             :      * @throw std::runtime_error
     104             :      */
     105             :     unsigned int readSizes(int fd, unsigned int pixel_format);
     106             : 
     107             :     std::vector<VideoSize> getSizeList() const;
     108             :     const VideoV4l2Size& getSize(VideoSize name) const;
     109             : 
     110             :     unsigned idx;
     111             :     std::string name;
     112             : 
     113             : private:
     114             :     void putCIFFirst();
     115             :     std::vector<VideoV4l2Size> sizes_;
     116             : };
     117             : 
     118             : class VideoDeviceImpl
     119             : {
     120             : public:
     121             :     /**
     122             :      * @throw std::runtime_error
     123             :      */
     124             :     VideoDeviceImpl(const std::string& id, const std::string& path);
     125             : 
     126             :     std::string unique_id;
     127             :     std::string path;
     128             :     std::string name;
     129             : 
     130             :     std::vector<std::string> getChannelList() const;
     131             :     std::vector<VideoSize> getSizeList(const std::string& channel) const;
     132             :     std::vector<FrameRate> getRateList(const std::string& channel, VideoSize size) const;
     133             : 
     134             :     DeviceParams getDeviceParams() const;
     135             :     void setDeviceParams(const DeviceParams&);
     136             : 
     137             : private:
     138             :     std::vector<VideoV4l2Channel> channels_;
     139             :     const VideoV4l2Channel& getChannel(const std::string& name) const;
     140             : 
     141             :     /* Preferences */
     142             :     VideoV4l2Channel channel_;
     143             :     VideoV4l2Size size_;
     144             :     VideoV4l2Rate rate_;
     145             : };
     146             : 
     147             : static const unsigned pixelformats_supported[] = {
     148             :     /* pixel format        depth  description   */
     149             : 
     150             :     /* preferred formats, they can be fed directly to the video encoder */
     151             :     V4L2_PIX_FMT_YUV420,  /* 12  YUV 4:2:0     */
     152             :     V4L2_PIX_FMT_YUV422P, /* 16  YVU422 planar */
     153             :     V4L2_PIX_FMT_YUV444,  /* 16  xxxxyyyy uuuuvvvv */
     154             : 
     155             :     /* Luminance+Chrominance formats */
     156             :     V4L2_PIX_FMT_YVU410,  /*  9  YVU 4:1:0     */
     157             :     V4L2_PIX_FMT_YVU420,  /* 12  YVU 4:2:0     */
     158             :     V4L2_PIX_FMT_YUYV,    /* 16  YUV 4:2:2     */
     159             :     V4L2_PIX_FMT_YYUV,    /* 16  YUV 4:2:2     */
     160             :     V4L2_PIX_FMT_YVYU,    /* 16 YVU 4:2:2 */
     161             :     V4L2_PIX_FMT_UYVY,    /* 16  YUV 4:2:2     */
     162             :     V4L2_PIX_FMT_VYUY,    /* 16  YUV 4:2:2     */
     163             :     V4L2_PIX_FMT_YUV411P, /* 16  YVU411 planar */
     164             :     V4L2_PIX_FMT_Y41P,    /* 12  YUV 4:1:1     */
     165             :     V4L2_PIX_FMT_YUV555,  /* 16  YUV-5-5-5     */
     166             :     V4L2_PIX_FMT_YUV565,  /* 16  YUV-5-6-5     */
     167             :     V4L2_PIX_FMT_YUV32,   /* 32  YUV-8-8-8-8   */
     168             :     V4L2_PIX_FMT_YUV410,  /*  9  YUV 4:1:0     */
     169             :     V4L2_PIX_FMT_HI240,   /*  8  8-bit color   */
     170             :     V4L2_PIX_FMT_HM12,    /*  8  YUV 4:2:0 16x16 macroblocks */
     171             : 
     172             :     /* two planes -- one Y, one Cr + Cb interleaved  */
     173             :     V4L2_PIX_FMT_NV12, /* 12  Y/CbCr 4:2:0  */
     174             :     V4L2_PIX_FMT_NV21, /* 12  Y/CrCb 4:2:0  */
     175             :     V4L2_PIX_FMT_NV16, /* 16  Y/CbCr 4:2:2  */
     176             :     V4L2_PIX_FMT_NV61, /* 16  Y/CrCb 4:2:2  */
     177             : 
     178             :     /* Compressed formats */
     179             :     V4L2_PIX_FMT_MJPEG,
     180             :     V4L2_PIX_FMT_JPEG,
     181             :     V4L2_PIX_FMT_DV,
     182             :     V4L2_PIX_FMT_MPEG,
     183             :     V4L2_PIX_FMT_H264,
     184             :     V4L2_PIX_FMT_H264_NO_SC,
     185             :     V4L2_PIX_FMT_H264_MVC,
     186             :     V4L2_PIX_FMT_H263,
     187             :     V4L2_PIX_FMT_MPEG1,
     188             :     V4L2_PIX_FMT_MPEG2,
     189             :     V4L2_PIX_FMT_MPEG4,
     190             :     V4L2_PIX_FMT_XVID,
     191             :     V4L2_PIX_FMT_VC1_ANNEX_G,
     192             :     V4L2_PIX_FMT_VC1_ANNEX_L,
     193             :     V4L2_PIX_FMT_VP8,
     194             : 
     195             : #if 0
     196             :     /* RGB formats */
     197             :     V4L2_PIX_FMT_RGB332,   /*  8  RGB-3-3-2     */
     198             :     V4L2_PIX_FMT_RGB444,   /* 16  xxxxrrrr ggggbbbb */
     199             :     V4L2_PIX_FMT_RGB555,   /* 16  RGB-5-5-5     */
     200             :     V4L2_PIX_FMT_RGB565,   /* 16  RGB-5-6-5     */
     201             :     V4L2_PIX_FMT_RGB555X,  /* 16  RGB-5-5-5 BE  */
     202             :     V4L2_PIX_FMT_RGB565X,  /* 16  RGB-5-6-5 BE  */
     203             :     V4L2_PIX_FMT_BGR666,   /* 18  BGR-6-6-6     */
     204             :     V4L2_PIX_FMT_BGR24,    /* 24  BGR-8-8-8     */
     205             :     V4L2_PIX_FMT_RGB24,    /* 24  RGB-8-8-8     */
     206             :     V4L2_PIX_FMT_BGR32,    /* 32  BGR-8-8-8-8   */
     207             :     V4L2_PIX_FMT_RGB32,    /* 32  RGB-8-8-8-8   */
     208             : 
     209             :     /* Grey formats */
     210             :     V4L2_PIX_FMT_GREY,     /*  8  Greyscale     */
     211             :     V4L2_PIX_FMT_Y4,       /*  4  Greyscale     */
     212             :     V4L2_PIX_FMT_Y6,       /*  6  Greyscale     */
     213             :     V4L2_PIX_FMT_Y10,      /* 10  Greyscale     */
     214             :     V4L2_PIX_FMT_Y16,      /* 16  Greyscale     */
     215             : 
     216             :     /* Palette formats */
     217             :     V4L2_PIX_FMT_PAL8,     /*  8  8-bit palette */
     218             : #endif
     219             : };
     220             : 
     221             : /* Returns a score for the given pixelformat
     222             :  *
     223             :  * Lowest score is the best, the first entries in the array are the formats
     224             :  * supported as an input for the video encoders.
     225             :  *
     226             :  * See pixelformats_supported array for the support list.
     227             :  */
     228             : static unsigned int
     229           0 : pixelformat_score(unsigned pixelformat)
     230             : {
     231           0 :     unsigned int formats_count = std::size(pixelformats_supported);
     232           0 :     for (unsigned int i = 0; i < formats_count; ++i) {
     233           0 :         if (pixelformats_supported[i] == pixelformat)
     234           0 :             return i;
     235             :     }
     236           0 :     return UINT_MAX - 1;
     237             : }
     238             : 
     239             : using std::vector;
     240             : using std::string;
     241             : 
     242             : vector<FrameRate>
     243           0 : VideoV4l2Size::getRateList() const
     244             : {
     245           0 :     vector<FrameRate> rates;
     246           0 :     rates.reserve(rates_.size());
     247           0 :     for (const auto& r : rates_)
     248           0 :         rates.emplace_back(r.frame_rate);
     249           0 :     return rates;
     250           0 : }
     251             : 
     252             : void
     253           0 : VideoV4l2Size::readFrameRates(int fd, unsigned int pixel_format)
     254             : {
     255           0 :     VideoV4l2Rate fallback_rate {1, 25, pixel_format};
     256             : 
     257             :     v4l2_frmivalenum frmival;
     258           0 :     ZEROVAR(frmival);
     259           0 :     frmival.pixel_format = pixel_format;
     260           0 :     frmival.width = width;
     261           0 :     frmival.height = height;
     262             : 
     263           0 :     if (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival)) {
     264           0 :         addRate(fallback_rate);
     265           0 :         JAMI_ERR("Unable to query frame interval for size");
     266           0 :         return;
     267             :     }
     268             : 
     269           0 :     if (frmival.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
     270           0 :         addRate(fallback_rate);
     271           0 :         JAMI_ERR("Continuous and stepwise Frame Intervals are not supported");
     272           0 :         return;
     273             :     }
     274             : 
     275             :     do {
     276           0 :         addRate({frmival.discrete.numerator, frmival.discrete.denominator, pixel_format});
     277           0 :         ++frmival.index;
     278           0 :     } while (!ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival));
     279             : }
     280             : 
     281             : VideoV4l2Rate
     282           0 : VideoV4l2Size::getRate(const FrameRate& rate) const
     283             : {
     284           0 :     for (const auto& item : rates_) {
     285           0 :         if (std::fabs((item.frame_rate - rate).real()) < 0.0001)
     286           0 :             return item;
     287             :     }
     288           0 :     return rates_.back();
     289             : }
     290             : 
     291             : void
     292           0 : VideoV4l2Size::addRate(VideoV4l2Rate new_rate)
     293             : {
     294           0 :     bool rate_found = false;
     295           0 :     for (auto& item : rates_) {
     296           0 :         if (item.frame_rate == new_rate.frame_rate) {
     297           0 :             if (pixelformat_score(item.pixel_format) > pixelformat_score(new_rate.pixel_format)) {
     298             :                 // Make sure we will use the prefered pixelformat (lower score means prefered format)
     299           0 :                 item.pixel_format = new_rate.pixel_format;
     300             :             }
     301           0 :             rate_found = true;
     302             :         }
     303             :     }
     304             : 
     305           0 :     if (!rate_found)
     306           0 :         rates_.push_back(new_rate);
     307           0 : }
     308             : 
     309          38 : VideoV4l2Channel::VideoV4l2Channel(unsigned idx, const char* s)
     310          38 :     : idx(idx)
     311          38 :     , name(s)
     312          38 :     , sizes_()
     313          38 : {}
     314             : 
     315             : std::vector<VideoSize>
     316           0 : VideoV4l2Channel::getSizeList() const
     317             : {
     318           0 :     vector<VideoSize> v;
     319           0 :     v.reserve(sizes_.size());
     320           0 :     for (const auto& item : sizes_)
     321           0 :         v.emplace_back(item.width, item.height);
     322             : 
     323           0 :     return v;
     324           0 : }
     325             : 
     326             : unsigned int
     327           0 : VideoV4l2Channel::readSizes(int fd, unsigned int pixelformat)
     328             : {
     329             :     v4l2_frmsizeenum frmsize;
     330           0 :     ZEROVAR(frmsize);
     331             : 
     332           0 :     frmsize.index = 0;
     333           0 :     frmsize.pixel_format = pixelformat;
     334             : 
     335           0 :     if (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) < 0) {
     336             :         v4l2_format fmt;
     337           0 :         ZEROVAR(fmt);
     338             : 
     339           0 :         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     340           0 :         if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0)
     341           0 :             throw std::runtime_error("Unable to get format");
     342             : 
     343           0 :         VideoV4l2Size size(fmt.fmt.pix.width, fmt.fmt.pix.height);
     344           0 :         size.readFrameRates(fd, fmt.fmt.pix.pixelformat);
     345           0 :         sizes_.push_back(size);
     346             : 
     347           0 :         return fmt.fmt.pix.pixelformat;
     348           0 :     }
     349             : 
     350           0 :     if (frmsize.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
     351             :         // We do not take care of V4L2_FRMSIZE_TYPE_CONTINUOUS or V4L2_FRMSIZE_TYPE_STEPWISE
     352           0 :         JAMI_ERR("Continuous Frame sizes not supported");
     353           0 :         return pixelformat;
     354             :     }
     355             : 
     356             :     // Real work starts here: attach framerates to sizes and update pixelformat information
     357             :     do {
     358           0 :         bool size_exists = false;
     359           0 :         VideoV4l2Size size(frmsize.discrete.width, frmsize.discrete.height);
     360             : 
     361           0 :         for (auto& item : sizes_) {
     362           0 :             if (item == size) {
     363           0 :                 size_exists = true;
     364             :                 // If a size already exist we add frame rates since there may be some
     365             :                 // frame rates available in one format that are not availabe in another.
     366           0 :                 item.readFrameRates(fd, frmsize.pixel_format);
     367             :             }
     368             :         }
     369             : 
     370           0 :         if (!size_exists) {
     371           0 :             size.readFrameRates(fd, frmsize.pixel_format);
     372           0 :             sizes_.push_back(size);
     373             :         }
     374             : 
     375           0 :         ++frmsize.index;
     376           0 :     } while (!ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize));
     377             : 
     378           0 :     return pixelformat;
     379             : }
     380             : 
     381             : // Put CIF resolution (352x288) first in the list since it is more prevalent in
     382             : // VoIP
     383             : void
     384           0 : VideoV4l2Channel::putCIFFirst()
     385             : {
     386           0 :     const auto iter = std::find_if(sizes_.begin(), sizes_.end(), [](const VideoV4l2Size& size) {
     387           0 :         return size.width == 352 and size.height == 258;
     388             :     });
     389             : 
     390           0 :     if (iter != sizes_.end() and iter != sizes_.begin())
     391           0 :         std::swap(*iter, *sizes_.begin());
     392           0 : }
     393             : 
     394             : void
     395           0 : VideoV4l2Channel::readFormats(int fd)
     396             : {
     397           0 :     if (ioctl(fd, VIDIOC_S_INPUT, &idx))
     398           0 :         throw std::runtime_error("VIDIOC_S_INPUT failed");
     399             : 
     400             :     v4l2_fmtdesc fmt;
     401           0 :     ZEROVAR(fmt);
     402           0 :     unsigned fmt_index = 0;
     403             : 
     404           0 :     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     405           0 :     while (!ioctl(fd, VIDIOC_ENUM_FMT, &fmt)) {
     406           0 :         if (fmt_index != fmt.index)
     407           0 :             break;
     408           0 :         readSizes(fd, fmt.pixelformat);
     409           0 :         fmt.index = ++fmt_index;
     410             :     }
     411             : 
     412           0 :     if (fmt_index == 0)
     413           0 :         throw std::runtime_error("Unable to enumerate formats");
     414             : 
     415           0 :     putCIFFirst();
     416           0 : }
     417             : 
     418             : const VideoV4l2Size&
     419           0 : VideoV4l2Channel::getSize(VideoSize s) const
     420             : {
     421           0 :     for (const auto& item : sizes_) {
     422           0 :         if (item.width == s.first && item.height == s.second)
     423           0 :             return item;
     424             :     }
     425             : 
     426           0 :     assert(not sizes_.empty());
     427           0 :     return sizes_.front();
     428             : }
     429             : 
     430          38 : VideoDeviceImpl::VideoDeviceImpl(const string& id, const std::string& path)
     431          38 :     : unique_id(id)
     432          38 :     , path(path)
     433          38 :     , name()
     434          38 :     , channels_()
     435          38 :     , channel_(-1, "")
     436          38 :     , size_(-1, -1)
     437          38 :     , rate_(-1, 1, 0)
     438             : {
     439          38 :     if (id == DEVICE_DESKTOP) {
     440          38 :         name = DEVICE_DESKTOP;
     441          38 :         rate_.frame_rate = 30;
     442          38 :         return;
     443             :     }
     444           0 :     int fd = open(path.c_str(), O_RDWR);
     445           0 :     if (fd == -1)
     446           0 :         throw std::runtime_error("Unable to open device");
     447             : 
     448             :     v4l2_capability cap;
     449           0 :     if (ioctl(fd, VIDIOC_QUERYCAP, &cap))
     450           0 :         throw std::runtime_error("Unable to query capabilities");
     451             : 
     452           0 :     if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
     453           0 :         throw std::runtime_error("Not a capture device");
     454             : 
     455           0 :     if (cap.capabilities & V4L2_CAP_TOUCH)
     456           0 :         throw std::runtime_error("Touch device, ignoring it");
     457             : 
     458           0 :     name = string(reinterpret_cast<const char*>(cap.card));
     459             : 
     460             :     v4l2_input input;
     461           0 :     ZEROVAR(input);
     462             :     unsigned idx;
     463           0 :     input.index = idx = 0;
     464           0 :     while (!ioctl(fd, VIDIOC_ENUMINPUT, &input)) {
     465           0 :         if (idx != input.index)
     466           0 :             break;
     467             : 
     468           0 :         if (input.type & V4L2_INPUT_TYPE_CAMERA) {
     469           0 :             VideoV4l2Channel channel(idx, (const char*) input.name);
     470           0 :             channel.readFormats(fd);
     471           0 :             if (not channel.getSizeList().empty())
     472           0 :                 channels_.push_back(channel);
     473           0 :         }
     474             : 
     475           0 :         input.index = ++idx;
     476             :     }
     477             : 
     478           0 :     ::close(fd);
     479           0 : }
     480             : 
     481             : string
     482           0 : VideoV4l2Rate::libAvPixelformat() const
     483             : {
     484           0 :     switch (pixel_format) {
     485             :     // Set codec name for those pixelformats.
     486             :     // Those  names can be found in libavcodec/codec_desc.c
     487           0 :     case V4L2_PIX_FMT_MJPEG:
     488           0 :         return "mjpeg";
     489           0 :     case V4L2_PIX_FMT_DV:
     490           0 :         return "dvvideo";
     491           0 :     case V4L2_PIX_FMT_MPEG:
     492             :     case V4L2_PIX_FMT_MPEG1:
     493           0 :         return "mpeg1video";
     494           0 :     case V4L2_PIX_FMT_H264:
     495             :     case V4L2_PIX_FMT_H264_NO_SC:
     496             :     case V4L2_PIX_FMT_H264_MVC:
     497           0 :         return "h264";
     498           0 :     case V4L2_PIX_FMT_H263:
     499           0 :         return "h263";
     500           0 :     case V4L2_PIX_FMT_MPEG2:
     501           0 :         return "mpeg2video";
     502           0 :     case V4L2_PIX_FMT_MPEG4:
     503           0 :         return "mpeg4";
     504           0 :     case V4L2_PIX_FMT_VC1_ANNEX_G:
     505             :     case V4L2_PIX_FMT_VC1_ANNEX_L:
     506           0 :         return "vc1";
     507           0 :     case V4L2_PIX_FMT_VP8:
     508           0 :         return "vp8";
     509           0 :     default: // Most pixel formats do not need any codec
     510           0 :         return "";
     511             :     }
     512             : }
     513             : 
     514             : vector<string>
     515         114 : VideoDeviceImpl::getChannelList() const
     516             : {
     517         114 :     if (unique_id == DEVICE_DESKTOP)
     518         228 :         return {"default"};
     519           0 :     vector<string> v;
     520           0 :     v.reserve(channels_.size());
     521           0 :     for (const auto& itr : channels_)
     522           0 :         v.push_back(itr.name);
     523             : 
     524           0 :     return v;
     525           0 : }
     526             : 
     527             : vector<VideoSize>
     528         106 : VideoDeviceImpl::getSizeList(const string& channel) const
     529             : {
     530         106 :     if (unique_id == DEVICE_DESKTOP) {
     531         106 :         return {VideoSize(0, 0)};
     532             :     }
     533           0 :     return getChannel(channel).getSizeList();
     534             : }
     535             : 
     536             : vector<FrameRate>
     537         106 : VideoDeviceImpl::getRateList(const string& channel, VideoSize size) const
     538             : {
     539         106 :     if (unique_id == DEVICE_DESKTOP) {
     540             :         return {FrameRate(5),
     541             :                 FrameRate(10),
     542             :                 FrameRate(15),
     543             :                 FrameRate(20),
     544             :                 FrameRate(25),
     545             :                 FrameRate(30),
     546             :                 FrameRate(60),
     547             :                 FrameRate(120),
     548         106 :                 FrameRate(144)};
     549             :     }
     550           0 :     return getChannel(channel).getSize(size).getRateList();
     551             : }
     552             : 
     553             : const VideoV4l2Channel&
     554           0 : VideoDeviceImpl::getChannel(const string& name) const
     555             : {
     556           0 :     for (const auto& item : channels_)
     557           0 :         if (item.name == name)
     558           0 :             return item;
     559             : 
     560           0 :     assert(not channels_.empty());
     561           0 :     return channels_.front();
     562             : }
     563             : 
     564             : DeviceParams
     565         391 : VideoDeviceImpl::getDeviceParams() const
     566             : {
     567         391 :     DeviceParams params;
     568         391 :     params.name = name;
     569         391 :     params.unique_id = unique_id;
     570         391 :     params.input = path;
     571         391 :     if (unique_id == DEVICE_DESKTOP) {
     572         391 :         const auto* env = std::getenv("WAYLAND_DISPLAY");
     573         391 :         if (!env || strlen(env) == 0) {
     574         391 :             params.format = "x11grab";
     575             :         } else {
     576           0 :             params.format = "lavfi";
     577           0 :             params.input = "pipewiregrab";
     578             :         }
     579         391 :         params.framerate = rate_.frame_rate;
     580         391 :         return params;
     581             :     }
     582           0 :     params.format = "video4linux2";
     583           0 :     params.channel_name = channel_.name;
     584           0 :     params.channel = channel_.idx;
     585           0 :     params.width = size_.width;
     586           0 :     params.height = size_.height;
     587           0 :     params.framerate = rate_.frame_rate;
     588           0 :     params.pixel_format = rate_.libAvPixelformat();
     589           0 :     return params;
     590           0 : }
     591             : 
     592             : void
     593          68 : VideoDeviceImpl::setDeviceParams(const DeviceParams& params)
     594             : {
     595          68 :     if (unique_id == DEVICE_DESKTOP) {
     596          68 :         rate_.frame_rate = params.framerate;
     597          68 :         return;
     598             :     }
     599             :     // Set preferences or fallback to defaults.
     600           0 :     channel_ = getChannel(params.channel_name);
     601           0 :     size_ = channel_.getSize({params.width, params.height});
     602             :     try {
     603           0 :         rate_ = size_.getRate(params.framerate);
     604           0 :     } catch (...) {
     605           0 :         rate_ = {};
     606           0 :     }
     607             : }
     608             : 
     609          38 : VideoDevice::VideoDevice(const std::string& id,
     610          38 :                          const std::vector<std::map<std::string, std::string>>& devInfo)
     611          38 :     : id_(id)
     612             : {
     613          76 :     deviceImpl_ = std::make_shared<VideoDeviceImpl>(id,
     614          38 :                                                     devInfo.empty() ? id
     615          76 :                                                                     : devInfo.at(0).at("devPath"));
     616          38 :     name = deviceImpl_->name;
     617          38 : }
     618             : 
     619             : DeviceParams
     620         391 : VideoDevice::getDeviceParams() const
     621             : {
     622         391 :     auto params = deviceImpl_->getDeviceParams();
     623         391 :     params.orientation = orientation_;
     624         391 :     return params;
     625             : }
     626             : 
     627             : void
     628          68 : VideoDevice::setDeviceParams(const DeviceParams& params)
     629             : {
     630          68 :     return deviceImpl_->setDeviceParams(params);
     631             : }
     632             : 
     633             : std::vector<std::string>
     634         114 : VideoDevice::getChannelList() const
     635             : {
     636         114 :     return deviceImpl_->getChannelList();
     637             : }
     638             : 
     639             : std::vector<VideoSize>
     640         106 : VideoDevice::getSizeList(const std::string& channel) const
     641             : {
     642         106 :     return deviceImpl_->getSizeList(channel);
     643             : }
     644             : 
     645             : std::vector<FrameRate>
     646         106 : VideoDevice::getRateList(const std::string& channel, VideoSize size) const
     647             : {
     648         106 :     return deviceImpl_->getRateList(channel, size);
     649             : }
     650             : 
     651          76 : VideoDevice::~VideoDevice() {}
     652             : 
     653             : } // namespace video
     654             : } // namespace jami

Generated by: LCOV version 1.14