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-04-26 09:41:19 Functions: 16 30 53.3 %

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

Generated by: LCOV version 1.14