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