LCOV - code coverage report
Current view: top level - foo/src/client - videomanager.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 156 418 37.3 %
Date: 2026-02-28 10:41:24 Functions: 24 73 32.9 %

          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       33789 : MediaFrame::MediaFrame()
      49       33789 :     : frame_ {av_frame_alloc()}
      50             : {
      51       33785 :     if (not frame_)
      52           0 :         throw std::bad_alloc();
      53       33786 : }
      54             : 
      55             : void
      56        5593 : MediaFrame::copyFrom(const MediaFrame& o)
      57             : {
      58        5593 :     reset();
      59        5593 :     if (o.frame_) {
      60        5593 :         av_frame_ref(frame_.get(), o.frame_.get());
      61        5593 :         av_frame_copy_props(frame_.get(), o.frame_.get());
      62             :     }
      63             : 
      64        5593 :     if (o.packet_) {
      65           0 :         packet_.reset(av_packet_alloc());
      66           0 :         av_packet_ref(packet_.get(), o.packet_.get());
      67             :     }
      68        5593 : }
      69             : 
      70             : void
      71        5642 : MediaFrame::reset() noexcept
      72             : {
      73        5642 :     if (frame_)
      74        5642 :         av_frame_unref(frame_.get());
      75        5642 :     packet_.reset();
      76        5642 : }
      77             : 
      78             : void
      79           0 : MediaFrame::setPacket(PacketBuffer&& pkt)
      80             : {
      81           0 :     packet_ = std::move(pkt);
      82           0 : }
      83             : 
      84        9957 : AudioFrame::AudioFrame(const jami::AudioFormat& format, size_t nb_samples)
      85        9957 :     : MediaFrame()
      86             : {
      87        9957 :     setFormat(format);
      88        9957 :     if (nb_samples)
      89           8 :         reserve(nb_samples);
      90        9957 : }
      91             : 
      92             : void
      93        9957 : AudioFrame::setFormat(const jami::AudioFormat& format)
      94             : {
      95        9957 :     auto* d = pointer();
      96        9957 :     av_channel_layout_default(&d->ch_layout, static_cast<int>(format.nb_channels));
      97        9957 :     d->sample_rate = static_cast<int>(format.sample_rate);
      98        9957 :     d->format = format.sampleFormat;
      99        9957 : }
     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        3840 :                 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_ERR() << "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       32851 : VideoFrame::~VideoFrame()
     203             : {
     204       23681 :     if (releaseBufferCb_)
     205           0 :         releaseBufferCb_(ptr_);
     206       32851 : }
     207             : 
     208             : void
     209        5642 : VideoFrame::reset() noexcept
     210             : {
     211        5642 :     MediaFrame::reset();
     212        5642 :     allocated_ = false;
     213        5642 :     releaseBufferCb_ = {};
     214        5642 : }
     215             : 
     216             : void
     217        5593 : VideoFrame::copyFrom(const VideoFrame& o)
     218             : {
     219        5593 :     MediaFrame::copyFrom(o);
     220        5593 :     ptr_ = o.ptr_;
     221        5593 :     allocated_ = o.allocated_;
     222        5593 : }
     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       22373 : VideoFrame::format() const noexcept
     232             : {
     233       22373 :     return frame_->format;
     234             : }
     235             : 
     236             : int
     237       23010 : VideoFrame::width() const noexcept
     238             : {
     239       23010 :     return frame_->width;
     240             : }
     241             : 
     242             : int
     243       31819 : VideoFrame::height() const noexcept
     244             : {
     245       31819 :     return frame_->height;
     246             : }
     247             : 
     248             : void
     249       18035 : VideoFrame::setGeometry(int format, int width, int height) noexcept
     250             : {
     251       18035 :     frame_->format = format;
     252       18035 :     frame_->width = width;
     253       18035 :     frame_->height = height;
     254       18035 : }
     255             : 
     256             : void
     257       17986 : VideoFrame::reserve(int format, int width, int height)
     258             : {
     259       17986 :     auto* libav_frame = frame_.get();
     260             : 
     261       17986 :     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       17986 :     setGeometry(format, width, height);
     268       17986 :     if (av_frame_get_buffer(libav_frame, 32))
     269           0 :         throw std::bad_alloc();
     270       17986 :     allocated_ = true;
     271       17986 :     releaseBufferCb_ = {};
     272       17986 : }
     273             : 
     274             : void
     275          49 : VideoFrame::setFromMemory(uint8_t* ptr, int format, int width, int height) noexcept
     276             : {
     277          49 :     reset();
     278          49 :     setGeometry(format, width, height);
     279          49 :     if (not ptr)
     280           0 :         return;
     281          49 :     av_image_fill_arrays(frame_->data,
     282          49 :                          frame_->linesize,
     283             :                          (uint8_t*) ptr,
     284          49 :                          (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       15038 : VideoFrame::getOrientation() const
     322             : {
     323       15038 :     int32_t* matrix {nullptr};
     324       15038 :     if (auto* p = packet()) {
     325           0 :         matrix = reinterpret_cast<int32_t*>(av_packet_get_side_data(p, AV_PKT_DATA_DISPLAYMATRIX, nullptr));
     326       15038 :     } else if (const auto* p = pointer()) {
     327       15038 :         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       15038 :     if (matrix) {
     332           0 :         double angle = av_display_rotation_get(matrix);
     333           0 :         return std::isnan(angle) ? 0 : -(int) angle;
     334             :     }
     335       15038 :     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_DBG("Setting default device to %s", deviceId.c_str());
     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             : }
     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_WARN("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_WARN("No sink found for id '%s'", sinkId.c_str());
     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_WARN("No sink found for id '%s'", sinkId.c_str());
     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             : }
     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_DBG("%s 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_DBG("%s 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        2721 : getVideoDeviceMonitor()
     684             : {
     685        2721 :     if (auto* vm = jami::Manager::instance().getVideoManager())
     686        2715 :         return &vm->videoDeviceMonitor;
     687           6 :     return {};
     688             : }
     689             : 
     690             : std::shared_ptr<video::VideoInput>
     691         135 : getVideoInput(const std::string& resource, video::VideoInputMode inputMode, const std::string& sink)
     692             : {
     693         135 :     auto sinkId = sink.empty() ? resource : sink;
     694         135 :     auto* vmgr = Manager::instance().getVideoManager();
     695         135 :     if (!vmgr)
     696           0 :         return {};
     697         135 :     std::lock_guard<std::mutex> lk(vmgr->videoMutex);
     698         135 :     auto it = vmgr->videoInputs.find(sinkId);
     699         135 :     if (it != vmgr->videoInputs.end()) {
     700         119 :         if (auto input = it->second.lock()) {
     701          73 :             return input;
     702         119 :         }
     703             :     }
     704             : 
     705          62 :     auto input = std::make_shared<video::VideoInput>(inputMode, resource, sinkId);
     706          62 :     vmgr->videoInputs[sinkId] = input;
     707          62 :     return input;
     708         135 : }
     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         278 : getAudioInput(const std::string& device)
     719             : {
     720         278 :     auto* vmgr = Manager::instance().getVideoManager();
     721         278 :     if (!vmgr)
     722           0 :         return {};
     723         278 :     std::lock_guard<std::mutex> lk(vmgr->audioMutex);
     724             : 
     725             :     // erase expired audio inputs
     726        1168 :     for (auto it = vmgr->audioInputs.cbegin(); it != vmgr->audioInputs.cend();) {
     727         890 :         if (it->second.expired())
     728         212 :             it = vmgr->audioInputs.erase(it);
     729             :         else
     730         678 :             ++it;
     731             :     }
     732             : 
     733         278 :     auto it = vmgr->audioInputs.find(device);
     734         278 :     if (it != vmgr->audioInputs.end()) {
     735          42 :         if (auto input = it->second.lock()) {
     736          42 :             return input;
     737          42 :         }
     738             :     }
     739             : 
     740         236 :     auto input = std::make_shared<AudioInput>(device);
     741         236 :     vmgr->audioInputs[device] = input;
     742         236 :     return input;
     743         278 : }
     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         523 : closeMediaPlayer(const std::string& id)
     794             : {
     795         523 :     if (auto* vm = Manager::instance().getVideoManager()) {
     796         523 :         std::scoped_lock<std::mutex> lk(vm->mediaPlayersMutex);
     797         523 :         return vm->mediaPlayers.erase(id) > 0;
     798         523 :     }
     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 1.14