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

Generated by: LCOV version 1.14