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 : #pragma once 18 : 19 : #include "audio_format.h" 20 : #include "media_buffer.h" 21 : #include "noncopyable.h" 22 : 23 : #include <map> 24 : #include <set> 25 : #include <string> 26 : #include <mutex> 27 : #include <memory> 28 : 29 : namespace jami { 30 : 31 : class RingBuffer; 32 : 33 : class RingBufferPool 34 : { 35 : public: 36 : static const char* const DEFAULT_ID; 37 : 38 : RingBufferPool(); 39 : ~RingBufferPool(); 40 : 41 33 : int getInternalSamplingRate() const { return internalAudioFormat_.sample_rate; } 42 : 43 657 : AudioFormat getInternalAudioFormat() const { return internalAudioFormat_; } 44 : 45 : void setInternalSamplingRate(unsigned sr); 46 : 47 : void setInternalAudioFormat(AudioFormat format); 48 : 49 : /** 50 : * Bind two RingBuffer together (full duplex). 51 : * @param ringbufferId1 52 : * @param ringbufferId2 53 : */ 54 : void bindRingBuffers(const std::string &ringbufferId1, const std::string &ringbufferId2); 55 : 56 : /** 57 : * Unbind two RingBuffer (full duplex). 58 : */ 59 : void unbindRingBuffers(const std::string &ringbufferId1, const std::string &ringbufferId2); 60 : 61 : /** 62 : * Attaches a reader the specified source. 63 : * @param readerBufferId The ID of the RingBuffer that will act as the reader of the 64 : * sourceBuffer. 65 : * @param sourceBufferId The iID of the RingBuffer that will be the source (to be read from). 66 : */ 67 : void bindHalfDuplexOut(const std::string &readerBufferId, const std::string &sourceBufferId); 68 : 69 : /** 70 : * Detaches a reader from the specified source. 71 : * @param readerBufferId The ID of the RingBuffer that acts as the reader to be detached from the 72 : * sourceBuffer. 73 : * @param sourceBufferId The RingBuffer that serves as the source (being read from). 74 : */ 75 : void unBindHalfDuplexOut(const std::string &readerBufferId, const std::string &sourceBufferId); 76 : 77 : /** 78 : * Detaches a reader from all his sources. 79 : * @param readerBufferId The ID of the RingBuffer that acts as the reader to be detached from the 80 : * sources. 81 : */ 82 : void unBindAllHalfDuplexOut(const std::string &ringbufferId); 83 : 84 : /** 85 : * Detaches a source from all its readers. 86 : * @param sourceBufferId The ID of the RingBuffer that serves as the source (being read from). 87 : */ 88 : void unBindAllHalfDuplexIn(const std::string &sourceBufferId); 89 : 90 : void unBindAll(const std::string& ringbufferId); 91 : 92 : bool waitForDataAvailable(const std::string& ringbufferId, 93 : const std::chrono::microseconds& max_wait) const; 94 : 95 : std::shared_ptr<AudioFrame> getData(const std::string& ringbufferId); 96 : 97 : std::shared_ptr<AudioFrame> getAvailableData(const std::string& ringbufferId); 98 : 99 : size_t availableForGet(const std::string& ringbufferId) const; 100 : 101 : size_t discard(size_t toDiscard, const std::string& ringbufferId); 102 : 103 : void flush(const std::string& ringbufferId); 104 : 105 : void flushAllBuffers(); 106 : 107 : /** 108 : * Create a new ringbuffer with a default readoffset. 109 : * This class keeps a weak reference on returned pointer, 110 : * so the caller is responsible of the referred instance. 111 : */ 112 : std::shared_ptr<RingBuffer> createRingBuffer(const std::string& id); 113 : 114 : /** 115 : * Obtain a shared pointer on a RingBuffer given by its ID. 116 : * If the ID doesn't match to any RingBuffer, the shared pointer 117 : * is empty. This non-const version flushes internal weak pointers 118 : * if the ID was used and the associated RingBuffer has been deleted. 119 : */ 120 : std::shared_ptr<RingBuffer> getRingBuffer(const std::string& id); 121 : 122 : /** 123 : * Works as non-const getRingBuffer, without the weak reference flush. 124 : */ 125 : std::shared_ptr<RingBuffer> getRingBuffer(const std::string& id) const; 126 : 127 : bool isAudioMeterActive(const std::string& id); 128 : void setAudioMeterState(const std::string& id, bool state); 129 : 130 : private: 131 : NON_COPYABLE(RingBufferPool); 132 : 133 : // A set of RingBuffers readable by a call 134 : using ReadBindings 135 : = std::set<std::shared_ptr<RingBuffer>, std::owner_less<std::shared_ptr<RingBuffer>>>; 136 : 137 : const ReadBindings* getReadBindings(const std::string& ringbufferId) const; 138 : ReadBindings* getReadBindings(const std::string& ringbufferId); 139 : 140 : void removeReadBindings(const std::string& ringbufferId); 141 : 142 : /** 143 : * Attaches a reader to the specified source. 144 : * @param sourceBuffer The RingBuffer that will be the source (to be read from). 145 : * @param readerBufferId The ID of the RingBuffer that will act as the reader of the 146 : * sourceBuffer. 147 : */ 148 : void addReaderToRingBuffer(const std::shared_ptr<RingBuffer> &sourceBuffer, 149 : const std::string &readerBufferId); 150 : 151 : /** 152 : * Detaches a reader from the specified source. 153 : * @param sourceBuffer The RingBuffer that serves as the source (being read from). 154 : * @param readerBufferId The ID of the RingBuffer that acts as the reader to be detached from the 155 : * sourceBuffer. 156 : */ 157 : void removeReaderFromRingBuffer(const std::shared_ptr<RingBuffer> &sourceBuffer, 158 : const std::string &readerBufferId); 159 : 160 : // A cache of created RingBuffers listed by IDs. 161 : std::map<std::string, std::weak_ptr<RingBuffer>> ringBufferMap_ {}; 162 : 163 : // A map of which RingBuffers a call has some ReadOffsets 164 : std::map<std::string, ReadBindings> readBindingsMap_ {}; 165 : 166 : mutable std::recursive_mutex stateLock_ {}; 167 : 168 : AudioFormat internalAudioFormat_ {AudioFormat::DEFAULT()}; 169 : 170 : std::shared_ptr<RingBuffer> defaultRingBuffer_; 171 : }; 172 : 173 : } // namespace jami