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 32 : int getInternalSamplingRate() const { return internalAudioFormat_.sample_rate; } 42 : 43 637 : 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, const std::chrono::microseconds& max_wait) const; 93 : 94 : std::shared_ptr<AudioFrame> getData(const std::string& ringbufferId); 95 : 96 : std::shared_ptr<AudioFrame> getAvailableData(const std::string& ringbufferId); 97 : 98 : size_t availableForGet(const std::string& ringbufferId) const; 99 : 100 : size_t discard(size_t toDiscard, const std::string& ringbufferId); 101 : 102 : void flush(const std::string& ringbufferId); 103 : 104 : void flushAllBuffers(); 105 : 106 : /** 107 : * Create a new ringbuffer with a default readoffset. 108 : * This class keeps a weak reference on returned pointer, 109 : * so the caller is responsible of the referred instance. 110 : */ 111 : std::shared_ptr<RingBuffer> createRingBuffer(const std::string& id); 112 : 113 : /** 114 : * Obtain a shared pointer on a RingBuffer given by its ID. 115 : * If the ID doesn't match to any RingBuffer, the shared pointer 116 : * is empty. This non-const version flushes internal weak pointers 117 : * if the ID was used and the associated RingBuffer has been deleted. 118 : */ 119 : std::shared_ptr<RingBuffer> getRingBuffer(const std::string& id); 120 : 121 : /** 122 : * Works as non-const getRingBuffer, without the weak reference flush. 123 : */ 124 : std::shared_ptr<RingBuffer> getRingBuffer(const std::string& id) const; 125 : 126 : bool isAudioMeterActive(const std::string& id); 127 : void setAudioMeterState(const std::string& id, bool state); 128 : 129 : private: 130 : NON_COPYABLE(RingBufferPool); 131 : 132 : // A set of RingBuffers readable by a call 133 : using ReadBindings = std::set<std::shared_ptr<RingBuffer>, std::owner_less<std::shared_ptr<RingBuffer>>>; 134 : 135 : const ReadBindings* getReadBindings(const std::string& ringbufferId) const; 136 : ReadBindings* getReadBindings(const std::string& ringbufferId); 137 : 138 : void removeReadBindings(const std::string& ringbufferId); 139 : 140 : /** 141 : * Attaches a reader to the specified source. 142 : * @param sourceBuffer The RingBuffer that will be the source (to be read from). 143 : * @param readerBufferId The ID of the RingBuffer that will act as the reader of the 144 : * sourceBuffer. 145 : */ 146 : void addReaderToRingBuffer(const std::shared_ptr<RingBuffer>& sourceBuffer, const std::string& readerBufferId); 147 : 148 : /** 149 : * Detaches a reader from the specified source. 150 : * @param sourceBuffer The RingBuffer that serves as the source (being read from). 151 : * @param readerBufferId The ID of the RingBuffer that acts as the reader to be detached from the 152 : * sourceBuffer. 153 : */ 154 : void removeReaderFromRingBuffer(const std::shared_ptr<RingBuffer>& sourceBuffer, const std::string& readerBufferId); 155 : 156 : // A cache of created RingBuffers listed by IDs. 157 : std::map<std::string, std::weak_ptr<RingBuffer>> ringBufferMap_ {}; 158 : 159 : // A map of which RingBuffers a call has some ReadOffsets 160 : std::map<std::string, ReadBindings> readBindingsMap_ {}; 161 : 162 : mutable std::recursive_mutex stateLock_ {}; 163 : 164 : AudioFormat internalAudioFormat_ {AudioFormat::DEFAULT()}; 165 : 166 : std::shared_ptr<RingBuffer> defaultRingBuffer_; 167 : }; 168 : 169 : } // namespace jami