LCOV - code coverage report
Current view: top level - src/client - videomanager.cpp (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 36.9 % 420 155
Test Date: 2026-06-13 09:18:46 Functions: 28.2 % 85 24

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

Generated by: LCOV version 2.0-1