LCOV - code coverage report
Current view: top level - foo/src/client - videomanager.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 150 410 36.6 %
Date: 2025-12-18 10:07:43 Functions: 24 73 32.9 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2025 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 "videomanager_interface.h"
      19             : #include "videomanager.h"
      20             : #include "localrecorder.h"
      21             : #include "localrecordermanager.h"
      22             : #include "libav_utils.h"
      23             : #include "video/video_input.h"
      24             : #include "video/video_device_monitor.h"
      25             : #include "account.h"
      26             : #include "logger.h"
      27             : #include "manager.h"
      28             : #include "system_codec_container.h"
      29             : #ifdef ENABLE_VIDEO
      30             : #include "video/sinkclient.h"
      31             : #endif
      32             : #include "client/ring_signal.h"
      33             : #include "audio/ringbufferpool.h"
      34             : #include "jami/media_const.h"
      35             : #include "libav_utils.h"
      36             : #include "call_const.h"
      37             : #include "system_codec_container.h"
      38             : 
      39             : #include <functional>
      40             : #include <memory>
      41             : #include <string>
      42             : #include <vector>
      43             : #include <new> // std::bad_alloc
      44             : #include <algorithm>
      45             : #include <cstdlib>
      46             : #include <cstring> // std::memset
      47             : #include <ciso646> // fix windows compiler bug
      48             : 
      49             : extern "C" {
      50             : #include <libavutil/display.h>
      51             : }
      52             : 
      53             : namespace libjami {
      54             : 
      55       34330 : MediaFrame::MediaFrame()
      56       34330 :     : frame_ {av_frame_alloc()}
      57             : {
      58       34319 :     if (not frame_)
      59           0 :         throw std::bad_alloc();
      60       34321 : }
      61             : 
      62             : void
      63        5752 : MediaFrame::copyFrom(const MediaFrame& o)
      64             : {
      65        5752 :     reset();
      66        5752 :     if (o.frame_) {
      67        5752 :         av_frame_ref(frame_.get(), o.frame_.get());
      68        5752 :         av_frame_copy_props(frame_.get(), o.frame_.get());
      69             :     }
      70             : 
      71        5752 :     if (o.packet_) {
      72           0 :         packet_.reset(av_packet_alloc());
      73           0 :         av_packet_ref(packet_.get(), o.packet_.get());
      74             :     }
      75        5752 : }
      76             : 
      77             : void
      78        5802 : MediaFrame::reset() noexcept
      79             : {
      80        5802 :     if (frame_)
      81        5802 :         av_frame_unref(frame_.get());
      82        5802 :     packet_.reset();
      83        5802 : }
      84             : 
      85             : void
      86           0 : MediaFrame::setPacket(PacketBuffer&& pkt)
      87             : {
      88           0 :     packet_ = std::move(pkt);
      89           0 : }
      90             : 
      91        9941 : AudioFrame::AudioFrame(const jami::AudioFormat& format, size_t nb_samples)
      92        9941 :     : MediaFrame()
      93             : {
      94        9941 :     setFormat(format);
      95        9941 :     if (nb_samples)
      96           8 :         reserve(nb_samples);
      97        9941 : }
      98             : 
      99             : void
     100        9941 : AudioFrame::setFormat(const jami::AudioFormat& format)
     101             : {
     102        9941 :     auto d = pointer();
     103        9941 :     av_channel_layout_default(&d->ch_layout, format.nb_channels);
     104        9941 :     d->sample_rate = format.sample_rate;
     105        9941 :     d->format = format.sampleFormat;
     106        9941 : }
     107             : 
     108             : jami::AudioFormat
     109           0 : AudioFrame::getFormat() const
     110             : {
     111           0 :     return {(unsigned) frame_->sample_rate, (unsigned) frame_->ch_layout.nb_channels, (AVSampleFormat) frame_->format};
     112             : }
     113             : 
     114             : size_t
     115           0 : AudioFrame::getFrameSize() const
     116             : {
     117           0 :     return frame_->nb_samples;
     118             : }
     119             : 
     120             : void
     121           8 : AudioFrame::reserve(size_t nb_samples)
     122             : {
     123           8 :     if (nb_samples != 0) {
     124           8 :         auto d = pointer();
     125           8 :         d->nb_samples = nb_samples;
     126             :         int err;
     127           8 :         if ((err = av_frame_get_buffer(d, 0)) < 0) {
     128           0 :             throw std::bad_alloc();
     129             :         }
     130             :     }
     131           8 : }
     132             : 
     133             : void
     134           1 : AudioFrame::mix(const AudioFrame& frame)
     135             : {
     136           1 :     auto& f = *pointer();
     137           1 :     auto& fIn = *frame.pointer();
     138           1 :     if (f.ch_layout.nb_channels != fIn.ch_layout.nb_channels || f.format != fIn.format
     139           1 :         || f.sample_rate != fIn.sample_rate) {
     140           0 :         throw std::invalid_argument("Unable to mix frames with different formats");
     141             :     }
     142           1 :     if (f.nb_samples == 0) {
     143           0 :         reserve(fIn.nb_samples);
     144           0 :         jami::libav_utils::fillWithSilence(&f);
     145           1 :     } else if (f.nb_samples != fIn.nb_samples) {
     146           0 :         throw std::invalid_argument("Unable to mix frames with different length");
     147             :     }
     148           1 :     AVSampleFormat fmt = (AVSampleFormat) f.format;
     149           1 :     bool isPlanar = av_sample_fmt_is_planar(fmt);
     150           1 :     unsigned samplesPerChannel = isPlanar ? f.nb_samples : f.nb_samples * f.ch_layout.nb_channels;
     151           1 :     unsigned channels = isPlanar ? f.ch_layout.nb_channels : 1;
     152           1 :     if (fmt == AV_SAMPLE_FMT_S16 || fmt == AV_SAMPLE_FMT_S16P) {
     153           2 :         for (unsigned i = 0; i < channels; i++) {
     154           1 :             auto c = (int16_t*) f.extended_data[i];
     155           1 :             auto cIn = (int16_t*) fIn.extended_data[i];
     156        1921 :             for (unsigned s = 0; s < samplesPerChannel; s++) {
     157        3840 :                 c[s] = std::clamp((int32_t) c[s] + (int32_t) cIn[s],
     158        1920 :                                   (int32_t) std::numeric_limits<int16_t>::min(),
     159        3840 :                                   (int32_t) std::numeric_limits<int16_t>::max());
     160             :             }
     161             :         }
     162           1 :     } else if (fmt == AV_SAMPLE_FMT_FLT || fmt == AV_SAMPLE_FMT_FLTP) {
     163           0 :         for (unsigned i = 0; i < channels; i++) {
     164           0 :             auto c = (float*) f.extended_data[i];
     165           0 :             auto cIn = (float*) fIn.extended_data[i];
     166           0 :             for (unsigned s = 0; s < samplesPerChannel; s++) {
     167           0 :                 c[s] += cIn[s];
     168             :             }
     169             :         }
     170           0 :     } else {
     171           0 :         throw std::invalid_argument(std::string("Unsupported format for mixing: ") + av_get_sample_fmt_name(fmt));
     172             :     }
     173           1 : }
     174             : 
     175             : float
     176           0 : AudioFrame::calcRMS() const
     177             : {
     178           0 :     double rms = 0.0;
     179           0 :     auto fmt = static_cast<AVSampleFormat>(frame_->format);
     180           0 :     bool planar = av_sample_fmt_is_planar(fmt);
     181           0 :     int perChannel = planar ? frame_->nb_samples : frame_->nb_samples * frame_->ch_layout.nb_channels;
     182           0 :     int channels = planar ? frame_->ch_layout.nb_channels : 1;
     183           0 :     if (fmt == AV_SAMPLE_FMT_S16 || fmt == AV_SAMPLE_FMT_S16P) {
     184           0 :         for (int c = 0; c < channels; ++c) {
     185           0 :             auto buf = reinterpret_cast<int16_t*>(frame_->extended_data[c]);
     186           0 :             for (int i = 0; i < perChannel; ++i) {
     187           0 :                 auto sample = buf[i] * 0.000030517578125f;
     188           0 :                 rms += sample * sample;
     189             :             }
     190             :         }
     191           0 :     } else if (fmt == AV_SAMPLE_FMT_FLT || fmt == AV_SAMPLE_FMT_FLTP) {
     192           0 :         for (int c = 0; c < channels; ++c) {
     193           0 :             auto buf = reinterpret_cast<float*>(frame_->extended_data[c]);
     194           0 :             for (int i = 0; i < perChannel; ++i) {
     195           0 :                 rms += buf[i] * buf[i];
     196             :             }
     197             :         }
     198           0 :     } else {
     199             :         // Should not happen
     200           0 :         JAMI_ERR() << "Unsupported format for getting volume level: " << av_get_sample_fmt_name(fmt);
     201           0 :         return 0.0;
     202             :     }
     203             :     // divide by the number of multi-byte samples
     204           0 :     return sqrt(rms / (frame_->nb_samples * frame_->ch_layout.nb_channels));
     205             : }
     206             : 
     207             : #ifdef ENABLE_VIDEO
     208             : 
     209       33599 : VideoFrame::~VideoFrame()
     210             : {
     211       24238 :     if (releaseBufferCb_)
     212           0 :         releaseBufferCb_(ptr_);
     213       33599 : }
     214             : 
     215             : void
     216        5802 : VideoFrame::reset() noexcept
     217             : {
     218        5802 :     MediaFrame::reset();
     219        5802 :     allocated_ = false;
     220        5802 :     releaseBufferCb_ = {};
     221        5802 : }
     222             : 
     223             : void
     224        5752 : VideoFrame::copyFrom(const VideoFrame& o)
     225             : {
     226        5752 :     MediaFrame::copyFrom(o);
     227        5752 :     ptr_ = o.ptr_;
     228        5752 :     allocated_ = o.allocated_;
     229        5752 : }
     230             : 
     231             : size_t
     232           0 : VideoFrame::size() const noexcept
     233             : {
     234           0 :     return av_image_get_buffer_size((AVPixelFormat) frame_->format, frame_->width, frame_->height, 1);
     235             : }
     236             : 
     237             : int
     238       23009 : VideoFrame::format() const noexcept
     239             : {
     240       23009 :     return frame_->format;
     241             : }
     242             : 
     243             : int
     244       24315 : VideoFrame::width() const noexcept
     245             : {
     246       24315 :     return frame_->width;
     247             : }
     248             : 
     249             : int
     250       33311 : VideoFrame::height() const noexcept
     251             : {
     252       33311 :     return frame_->height;
     253             : }
     254             : 
     255             : void
     256       18414 : VideoFrame::setGeometry(int format, int width, int height) noexcept
     257             : {
     258       18414 :     frame_->format = format;
     259       18414 :     frame_->width = width;
     260       18414 :     frame_->height = height;
     261       18414 : }
     262             : 
     263             : void
     264       18364 : VideoFrame::reserve(int format, int width, int height)
     265             : {
     266       18364 :     auto libav_frame = frame_.get();
     267             : 
     268       18364 :     if (allocated_) {
     269             :         // nothing to do if same properties
     270           0 :         if (width == libav_frame->width and height == libav_frame->height and format == libav_frame->format)
     271           0 :             av_frame_unref(libav_frame);
     272             :     }
     273             : 
     274       18364 :     setGeometry(format, width, height);
     275       18364 :     if (av_frame_get_buffer(libav_frame, 32))
     276           0 :         throw std::bad_alloc();
     277       18364 :     allocated_ = true;
     278       18364 :     releaseBufferCb_ = {};
     279       18364 : }
     280             : 
     281             : void
     282          50 : VideoFrame::setFromMemory(uint8_t* ptr, int format, int width, int height) noexcept
     283             : {
     284          50 :     reset();
     285          50 :     setGeometry(format, width, height);
     286          50 :     if (not ptr)
     287           0 :         return;
     288          50 :     av_image_fill_arrays(frame_->data,
     289          50 :                          frame_->linesize,
     290             :                          (uint8_t*) ptr,
     291          50 :                          (AVPixelFormat) frame_->format,
     292             :                          width,
     293             :                          height,
     294             :                          1);
     295             : }
     296             : 
     297             : void
     298           0 : VideoFrame::setFromMemory(
     299             :     uint8_t* ptr, int format, int width, int height, const std::function<void(uint8_t*)>& cb) noexcept
     300             : {
     301           0 :     setFromMemory(ptr, format, width, height);
     302           0 :     if (cb) {
     303           0 :         releaseBufferCb_ = cb;
     304           0 :         ptr_ = ptr;
     305             :     }
     306           0 : }
     307             : 
     308             : void
     309           0 : VideoFrame::setReleaseCb(const std::function<void(uint8_t*)>& cb) noexcept
     310             : {
     311           0 :     if (cb) {
     312           0 :         releaseBufferCb_ = cb;
     313             :     }
     314           0 : }
     315             : 
     316             : void
     317           0 : VideoFrame::noise()
     318             : {
     319           0 :     auto f = frame_.get();
     320           0 :     if (f->data[0] == nullptr)
     321           0 :         return;
     322           0 :     for (std::size_t i = 0; i < size(); ++i) {
     323           0 :         f->data[0][i] = std::rand() & 255;
     324             :     }
     325             : }
     326             : 
     327             : int
     328       15401 : VideoFrame::getOrientation() const
     329             : {
     330       15401 :     int32_t* matrix {nullptr};
     331       15401 :     if (auto p = packet()) {
     332           0 :         matrix = reinterpret_cast<int32_t*>(av_packet_get_side_data(p, AV_PKT_DATA_DISPLAYMATRIX, nullptr));
     333       15401 :     } else if (auto p = pointer()) {
     334       15401 :         if (AVFrameSideData* side_data = av_frame_get_side_data(p, AV_FRAME_DATA_DISPLAYMATRIX)) {
     335           0 :             matrix = reinterpret_cast<int32_t*>(side_data->data);
     336             :         }
     337             :     }
     338       15401 :     if (matrix) {
     339           0 :         double angle = av_display_rotation_get(matrix);
     340           0 :         return std::isnan(angle) ? 0 : -(int) angle;
     341             :     }
     342       15401 :     return 0;
     343             : }
     344             : 
     345             : VideoFrame*
     346           0 : getNewFrame(std::string_view id)
     347             : {
     348           0 :     if (auto vm = jami::Manager::instance().getVideoManager())
     349           0 :         if (auto input = vm->getVideoInput(id))
     350           0 :             return &input->getNewFrame();
     351           0 :     JAMI_WARNING("getNewFrame: Unable to find input {}", id);
     352           0 :     return nullptr;
     353             : }
     354             : 
     355             : void
     356           0 : publishFrame(std::string_view id)
     357             : {
     358           0 :     if (auto vm = jami::Manager::instance().getVideoManager())
     359           0 :         if (auto input = vm->getVideoInput(id))
     360           0 :             input->publishFrame();
     361           0 : }
     362             : 
     363             : void
     364           0 : registerVideoHandlers(const std::map<std::string, std::shared_ptr<CallbackWrapperBase>>& handlers)
     365             : {
     366           0 :     registerSignalHandlers(handlers);
     367           0 : }
     368             : 
     369             : std::vector<std::string>
     370           0 : getDeviceList()
     371             : {
     372           0 :     if (auto vm = jami::Manager::instance().getVideoManager())
     373           0 :         return vm->videoDeviceMonitor.getDeviceList();
     374           0 :     return {};
     375             : }
     376             : 
     377             : VideoCapabilities
     378           0 : getCapabilities(const std::string& deviceId)
     379             : {
     380           0 :     if (auto vm = jami::Manager::instance().getVideoManager())
     381           0 :         return vm->videoDeviceMonitor.getCapabilities(deviceId);
     382           0 :     return {};
     383             : }
     384             : 
     385             : std::string
     386           0 : getDefaultDevice()
     387             : {
     388           0 :     if (auto vm = jami::Manager::instance().getVideoManager())
     389           0 :         return vm->videoDeviceMonitor.getDefaultDevice();
     390           0 :     return {};
     391             : }
     392             : 
     393             : void
     394           0 : setDefaultDevice(const std::string& deviceId)
     395             : {
     396           0 :     JAMI_DBG("Setting default device to %s", deviceId.c_str());
     397           0 :     if (auto vm = jami::Manager::instance().getVideoManager()) {
     398           0 :         if (vm->videoDeviceMonitor.setDefaultDevice(deviceId))
     399           0 :             jami::Manager::instance().saveConfig();
     400             :     }
     401           0 : }
     402             : 
     403             : void
     404           0 : setDeviceOrientation(const std::string& deviceId, int angle)
     405             : {
     406           0 :     if (auto vm = jami::Manager::instance().getVideoManager())
     407           0 :         vm->setDeviceOrientation(deviceId, angle);
     408           0 : }
     409             : 
     410             : std::map<std::string, std::string>
     411           0 : getDeviceParams(const std::string& deviceId)
     412             : {
     413           0 :     if (auto vm = jami::Manager::instance().getVideoManager()) {
     414           0 :         auto params = vm->videoDeviceMonitor.getDeviceParams(deviceId);
     415             :         return {{"format", params.format},
     416           0 :                 {"width", std::to_string(params.width)},
     417           0 :                 {"height", std::to_string(params.height)},
     418           0 :                 {"rate", params.framerate.to_string()}};
     419           0 :     }
     420           0 :     return {};
     421             : }
     422             : 
     423             : std::map<std::string, std::string>
     424           0 : getSettings(const std::string& deviceId)
     425             : {
     426           0 :     if (auto vm = jami::Manager::instance().getVideoManager()) {
     427           0 :         return vm->videoDeviceMonitor.getSettings(deviceId).to_map();
     428             :     }
     429           0 :     return {};
     430             : }
     431             : 
     432             : void
     433           0 : applySettings(const std::string& deviceId, const std::map<std::string, std::string>& settings)
     434             : {
     435           0 :     if (auto vm = jami::Manager::instance().getVideoManager()) {
     436           0 :         vm->videoDeviceMonitor.applySettings(deviceId, settings);
     437           0 :         jami::Manager::instance().saveConfig();
     438             :     }
     439           0 : }
     440             : 
     441             : std::string
     442           0 : openVideoInput(const std::string& path)
     443             : {
     444           0 :     if (auto vm = jami::Manager::instance().getVideoManager()) {
     445           0 :         auto id = path.empty() ? vm->videoDeviceMonitor.getMRLForDefaultDevice() : path;
     446           0 :         auto& input = vm->clientVideoInputs[id];
     447           0 :         if (not input) {
     448           0 :             input = jami::getVideoInput(id);
     449             :         }
     450           0 :         return id;
     451           0 :     }
     452           0 :     return {};
     453             : }
     454             : 
     455             : bool
     456           0 : closeVideoInput(const std::string& id)
     457             : {
     458           0 :     if (auto vm = jami::Manager::instance().getVideoManager())
     459           0 :         return vm->clientVideoInputs.erase(id) > 0;
     460           0 :     return false;
     461             : }
     462             : #endif
     463             : 
     464             : void
     465           0 : startAudioDevice()
     466             : {
     467           0 :     if (auto newPreview = jami::getAudioInput(jami::RingBufferPool::DEFAULT_ID)) {
     468           0 :         if (auto vm = jami::Manager::instance().getVideoManager())
     469           0 :             vm->audioPreview = newPreview;
     470           0 :         newPreview->switchInput("");
     471           0 :     }
     472           0 : }
     473             : 
     474             : void
     475           0 : stopAudioDevice()
     476             : {
     477           0 :     if (auto vm = jami::Manager::instance().getVideoManager())
     478           0 :         vm->audioPreview.reset();
     479           0 : }
     480             : 
     481             : std::string
     482           0 : startLocalMediaRecorder(const std::string& videoInputId, const std::string& filepath)
     483             : {
     484           0 :     auto rec = std::make_unique<jami::LocalRecorder>(videoInputId);
     485           0 :     rec->setPath(filepath);
     486             : 
     487             :     // retrieve final path (containing file extension)
     488           0 :     auto path = rec->getPath();
     489             : 
     490           0 :     auto& recordManager = jami::LocalRecorderManager::instance();
     491             : 
     492             :     try {
     493           0 :         recordManager.insertRecorder(path, std::move(rec));
     494           0 :     } catch (const std::invalid_argument&) {
     495           0 :         return "";
     496           0 :     }
     497             : 
     498           0 :     auto ret = recordManager.getRecorderByPath(path)->start();
     499           0 :     if (!ret) {
     500           0 :         recordManager.removeRecorderByPath(filepath);
     501           0 :         return "";
     502             :     }
     503             : 
     504           0 :     return path;
     505           0 : }
     506             : 
     507             : void
     508           0 : stopLocalRecorder(const std::string& filepath)
     509             : {
     510           0 :     jami::LocalRecorder* rec = jami::LocalRecorderManager::instance().getRecorderByPath(filepath);
     511           0 :     if (!rec) {
     512           0 :         JAMI_WARN("Unable to stop non existing local recorder.");
     513           0 :         return;
     514             :     }
     515             : 
     516           0 :     rec->stopRecording();
     517           0 :     jami::LocalRecorderManager::instance().removeRecorderByPath(filepath);
     518             : }
     519             : 
     520             : bool
     521           0 : registerSinkTarget(const std::string& sinkId, SinkTarget target)
     522             : {
     523             : #ifdef ENABLE_VIDEO
     524           0 :     if (auto sink = jami::Manager::instance().getSinkClient(sinkId)) {
     525           0 :         sink->registerTarget(std::move(target));
     526           0 :         return true;
     527             :     } else
     528           0 :         JAMI_WARN("No sink found for id '%s'", sinkId.c_str());
     529             : #endif
     530           0 :     return false;
     531             : }
     532             : 
     533             : #ifdef ENABLE_SHM
     534             : void
     535             : startShmSink(const std::string& sinkId, bool value)
     536             : {
     537             : #ifdef ENABLE_VIDEO
     538             :     if (auto sink = jami::Manager::instance().getSinkClient(sinkId))
     539             :         sink->enableShm(value);
     540             :     else
     541             :         JAMI_WARN("No sink found for id '%s'", sinkId.c_str());
     542             : #endif
     543             : }
     544             : #endif
     545             : 
     546             : std::map<std::string, std::string>
     547           0 : getRenderer(const std::string& callId)
     548             : {
     549             : #ifdef ENABLE_VIDEO
     550           0 :     if (auto sink = jami::Manager::instance().getSinkClient(callId))
     551             :         return {
     552             :             {libjami::Media::Details::CALL_ID, callId},
     553           0 :             {libjami::Media::Details::SHM_PATH, sink->openedName()},
     554           0 :             {libjami::Media::Details::WIDTH, std::to_string(sink->getWidth())},
     555           0 :             {libjami::Media::Details::HEIGHT, std::to_string(sink->getHeight())},
     556           0 :         };
     557             :     else
     558             : #endif
     559             :         return {
     560             :             {libjami::Media::Details::CALL_ID, callId},
     561             :             {libjami::Media::Details::SHM_PATH, ""},
     562             :             {libjami::Media::Details::WIDTH, "0"},
     563             :             {libjami::Media::Details::HEIGHT, "0"},
     564           0 :         };
     565             : }
     566             : 
     567             : std::string
     568           0 : createMediaPlayer(const std::string& path)
     569             : {
     570           0 :     return jami::createMediaPlayer(path);
     571             : }
     572             : 
     573             : bool
     574           0 : closeMediaPlayer(const std::string& id)
     575             : {
     576           0 :     return jami::closeMediaPlayer(id);
     577             : }
     578             : 
     579             : bool
     580           0 : pausePlayer(const std::string& id, const bool& pause)
     581             : {
     582           0 :     return jami::pausePlayer(id, pause);
     583             : }
     584             : 
     585             : bool
     586           0 : mutePlayerAudio(const std::string& id, const bool& mute)
     587             : {
     588           0 :     return jami::mutePlayerAudio(id, mute);
     589             : }
     590             : 
     591             : bool
     592           0 : playerSeekToTime(const std::string& id, const int& time)
     593             : {
     594           0 :     return jami::playerSeekToTime(id, time);
     595             : }
     596             : 
     597             : int64_t
     598           0 : getPlayerPosition(const std::string& id)
     599             : {
     600           0 :     return jami::getPlayerPosition(id);
     601             : }
     602             : 
     603             : int64_t
     604           0 : getPlayerDuration(const std::string& id)
     605             : {
     606           0 :     return jami::getPlayerDuration(id);
     607             : }
     608             : 
     609             : void
     610           0 : setAutoRestart(const std::string& id, const bool& restart)
     611             : {
     612           0 :     jami::setAutoRestart(id, restart);
     613           0 : }
     614             : 
     615             : bool
     616           0 : getDecodingAccelerated()
     617             : {
     618             : #ifdef ENABLE_HWACCEL
     619           0 :     return jami::Manager::instance().videoPreferences.getDecodingAccelerated();
     620             : #else
     621             :     return false;
     622             : #endif
     623             : }
     624             : 
     625             : void
     626           0 : setDecodingAccelerated(bool state)
     627             : {
     628             : #ifdef ENABLE_HWACCEL
     629           0 :     JAMI_DBG("%s hardware acceleration", (state ? "Enabling" : "Disabling"));
     630           0 :     if (jami::Manager::instance().videoPreferences.setDecodingAccelerated(state))
     631           0 :         jami::Manager::instance().saveConfig();
     632             : #endif
     633           0 : }
     634             : 
     635             : bool
     636           0 : getEncodingAccelerated()
     637             : {
     638             : #ifdef ENABLE_HWACCEL
     639           0 :     return jami::Manager::instance().videoPreferences.getEncodingAccelerated();
     640             : #else
     641             :     return false;
     642             : #endif
     643             : }
     644             : 
     645             : void
     646           0 : setEncodingAccelerated(bool state)
     647             : {
     648             : #ifdef ENABLE_HWACCEL
     649           0 :     JAMI_DBG("%s hardware acceleration", (state ? "Enabling" : "Disabling"));
     650           0 :     if (jami::Manager::instance().videoPreferences.setEncodingAccelerated(state))
     651           0 :         jami::Manager::instance().saveConfig();
     652             :     else
     653           0 :         return;
     654             : #endif
     655           0 :     for (const auto& acc : jami::Manager::instance().getAllAccounts()) {
     656           0 :         if (state)
     657           0 :             acc->setCodecActive(AV_CODEC_ID_HEVC);
     658             :         else
     659           0 :             acc->setCodecInactive(AV_CODEC_ID_HEVC);
     660             :         // Update and sort codecs
     661           0 :         acc->setActiveCodecs(acc->getActiveCodecs());
     662           0 :         jami::Manager::instance().saveConfig(acc);
     663           0 :     }
     664             : }
     665             : 
     666             : #if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
     667             : void
     668             : addVideoDevice(const std::string& node, const std::vector<std::map<std::string, std::string>>& devInfo)
     669             : {
     670             :     if (auto videoManager = jami::Manager::instance().getVideoManager()) {
     671             :         videoManager->videoDeviceMonitor.addDevice(node, devInfo);
     672             :     }
     673             : }
     674             : 
     675             : void
     676             : removeVideoDevice(const std::string& node)
     677             : {
     678             :     if (auto videoManager = jami::Manager::instance().getVideoManager()) {
     679             :         videoManager->videoDeviceMonitor.removeDevice(node);
     680             :     }
     681             : }
     682             : #endif
     683             : 
     684             : } // namespace libjami
     685             : 
     686             : namespace jami {
     687             : 
     688             : #ifdef ENABLE_VIDEO
     689             : video::VideoDeviceMonitor*
     690        2037 : getVideoDeviceMonitor()
     691             : {
     692        2037 :     if (auto vm = jami::Manager::instance().getVideoManager())
     693        2002 :         return &vm->videoDeviceMonitor;
     694          35 :     return {};
     695             : }
     696             : 
     697             : std::shared_ptr<video::VideoInput>
     698         144 : getVideoInput(const std::string& resource, video::VideoInputMode inputMode, const std::string& sink)
     699             : {
     700         144 :     auto sinkId = sink.empty() ? resource : sink;
     701         144 :     auto vmgr = Manager::instance().getVideoManager();
     702         144 :     if (!vmgr)
     703           0 :         return {};
     704         144 :     std::lock_guard<std::mutex> lk(vmgr->videoMutex);
     705         144 :     auto it = vmgr->videoInputs.find(sinkId);
     706         144 :     if (it != vmgr->videoInputs.end()) {
     707         127 :         if (auto input = it->second.lock()) {
     708          79 :             return input;
     709         127 :         }
     710             :     }
     711             : 
     712          65 :     auto input = std::make_shared<video::VideoInput>(inputMode, resource, sinkId);
     713          65 :     vmgr->videoInputs[sinkId] = input;
     714          65 :     return input;
     715         144 : }
     716             : 
     717             : void
     718           0 : VideoManager::setDeviceOrientation(const std::string& deviceId, int angle)
     719             : {
     720           0 :     videoDeviceMonitor.setDeviceOrientation(deviceId, angle);
     721           0 : }
     722             : #endif
     723             : 
     724             : std::shared_ptr<AudioInput>
     725         292 : getAudioInput(const std::string& device)
     726             : {
     727         292 :     auto vmgr = Manager::instance().getVideoManager();
     728         292 :     if (!vmgr)
     729           0 :         return {};
     730         292 :     std::lock_guard<std::mutex> lk(vmgr->audioMutex);
     731             : 
     732             :     // erase expired audio inputs
     733        1205 :     for (auto it = vmgr->audioInputs.cbegin(); it != vmgr->audioInputs.cend();) {
     734         913 :         if (it->second.expired())
     735         224 :             it = vmgr->audioInputs.erase(it);
     736             :         else
     737         689 :             ++it;
     738             :     }
     739             : 
     740         292 :     auto it = vmgr->audioInputs.find(device);
     741         292 :     if (it != vmgr->audioInputs.end()) {
     742          42 :         if (auto input = it->second.lock()) {
     743          42 :             return input;
     744          42 :         }
     745             :     }
     746             : 
     747         250 :     auto input = std::make_shared<AudioInput>(device);
     748         250 :     vmgr->audioInputs[device] = input;
     749         250 :     return input;
     750         292 : }
     751             : 
     752             : bool
     753           0 : VideoManager::hasRunningPlayers()
     754             : {
     755           0 :     if (auto vmgr = Manager::instance().getVideoManager())
     756           0 :         return !vmgr->mediaPlayers.empty();
     757           0 :     return false;
     758             : }
     759             : 
     760             : std::shared_ptr<MediaPlayer>
     761           6 : getMediaPlayer(const std::string& id)
     762             : {
     763           6 :     if (auto vmgr = Manager::instance().getVideoManager()) {
     764           6 :         auto it = vmgr->mediaPlayers.find(id);
     765           6 :         if (it != vmgr->mediaPlayers.end()) {
     766           6 :             return it->second;
     767             :         }
     768             :     }
     769           0 :     return {};
     770             : }
     771             : 
     772             : std::string
     773           6 : createMediaPlayer(const std::string& path)
     774             : {
     775           6 :     if (auto vmgr = Manager::instance().getVideoManager()) {
     776           6 :         auto& player = vmgr->mediaPlayers[path];
     777           6 :         if (!player) {
     778           6 :             player = std::make_shared<MediaPlayer>(path);
     779             :         }
     780           6 :         return path;
     781             :     }
     782           0 :     return {};
     783             : }
     784             : 
     785             : bool
     786           0 : pausePlayer(const std::string& id, bool pause)
     787             : {
     788           0 :     if (auto player = getMediaPlayer(id)) {
     789           0 :         player->pause(pause);
     790           0 :         return true;
     791           0 :     }
     792           0 :     return false;
     793             : }
     794             : 
     795             : bool
     796         535 : closeMediaPlayer(const std::string& id)
     797             : {
     798         535 :     if (auto vm = Manager::instance().getVideoManager())
     799         535 :         return vm->mediaPlayers.erase(id) > 0;
     800           0 :     return false;
     801             : }
     802             : 
     803             : bool
     804           0 : mutePlayerAudio(const std::string& id, bool mute)
     805             : {
     806           0 :     if (auto player = getMediaPlayer(id)) {
     807           0 :         player->muteAudio(mute);
     808           0 :         return true;
     809           0 :     }
     810           0 :     return false;
     811             : }
     812             : 
     813             : bool
     814           0 : playerSeekToTime(const std::string& id, int time)
     815             : {
     816           0 :     if (auto player = getMediaPlayer(id))
     817           0 :         return player->seekToTime(time);
     818           0 :     return false;
     819             : }
     820             : 
     821             : int64_t
     822           0 : getPlayerPosition(const std::string& id)
     823             : {
     824           0 :     if (auto player = getMediaPlayer(id))
     825           0 :         return player->getPlayerPosition();
     826           0 :     return -1;
     827             : }
     828             : 
     829             : int64_t
     830           0 : getPlayerDuration(const std::string& id)
     831             : {
     832           0 :     if (auto player = getMediaPlayer(id))
     833           0 :         return player->getPlayerDuration();
     834           0 :     return -1;
     835             : }
     836             : 
     837             : void
     838           0 : setAutoRestart(const std::string& id, bool restart)
     839             : {
     840           0 :     if (auto player = getMediaPlayer(id))
     841           0 :         player->setAutoRestart(restart);
     842           0 : }
     843             : 
     844             : } // namespace jami

Generated by: LCOV version 1.14