1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // This class provides a way to split a single media source into multiple sources. 18 // The constructor takes in the real mediaSource and createClient() can then be 19 // used to create multiple sources served from this real mediaSource. 20 // 21 // Usage: 22 // - Create MediaSourceSplitter by passing in a real mediaSource from which 23 // multiple duplicate channels are needed. 24 // - Create a client using createClient() and use it as any other mediaSource. 25 // 26 // Note that multiple clients can be created using createClient() and 27 // started/stopped in any order. MediaSourceSplitter stops the real source only 28 // when all clients have been stopped. 29 // 30 // If a new client is created/started after some existing clients have already 31 // started, the new client will start getting its read frames from the current 32 // time. 33 34 #ifndef MEDIA_SOURCE_SPLITTER_H_ 35 36 #define MEDIA_SOURCE_SPLITTER_H_ 37 38 #include <media/stagefright/MediaSource.h> 39 #include <utils/threads.h> 40 #include <utils/Vector.h> 41 #include <utils/RefBase.h> 42 43 namespace android { 44 45 class MediaBuffer; 46 class MetaData; 47 48 class MediaSourceSplitter : public RefBase { 49 public: 50 // Constructor 51 // mediaSource: The real mediaSource. The class keeps a reference to it to 52 // implement the various clients. 53 MediaSourceSplitter(sp<MediaSource> mediaSource); 54 55 ~MediaSourceSplitter(); 56 57 // Creates a new client of base type MediaSource. Multiple clients can be 58 // created which get their data through the same real mediaSource. These 59 // clients can then be used like any other MediaSource, all of which provide 60 // data from the same real source. 61 sp<MediaSource> createClient(); 62 63 private: 64 // Total number of clients created through createClient(). 65 int32_t mNumberOfClients; 66 67 // reference to the real MediaSource passed to the constructor. 68 sp<MediaSource> mSource; 69 70 // Stores pointer to the MediaBuffer read from the real MediaSource. 71 // All clients use this to implement the read() call. 72 MediaBuffer *mLastReadMediaBuffer; 73 74 // Status code for read from the real MediaSource. All clients return 75 // this for their read(). 76 status_t mLastReadStatus; 77 78 // Boolean telling whether the real MediaSource has started. 79 bool mSourceStarted; 80 81 // List of booleans, one for each client, storing whether the corresponding 82 // client's start() has been called. 83 Vector<bool> mClientsStarted; 84 85 // Stores the number of clients which are currently started. 86 int32_t mNumberOfClientsStarted; 87 88 // Since different clients call read() asynchronously, we need to keep track 89 // of what data is currently read into the mLastReadMediaBuffer. 90 // mCurrentReadBit stores the bit for the current read buffer. This bit 91 // flips each time a new buffer is read from the source. 92 // mClientsDesiredReadBit stores the bit for the next desired read buffer 93 // for each client. This bit flips each time read() is completed for this 94 // client. 95 bool mCurrentReadBit; 96 Vector<bool> mClientsDesiredReadBit; 97 98 // Number of clients whose current read has been completed. 99 int32_t mNumberOfCurrentReads; 100 101 // Boolean telling whether the last read has been completed for all clients. 102 // The variable is reset to false each time buffer is read from the real 103 // source. 104 bool mLastReadCompleted; 105 106 // A global mutex for access to critical sections. 107 Mutex mLock; 108 109 // Condition variable for waiting on read from source to complete. 110 Condition mReadFromSourceCondition; 111 112 // Condition variable for waiting on all client's last read to complete. 113 Condition mAllReadsCompleteCondition; 114 115 // Functions used by Client to implement the MediaSource interface. 116 117 // If the real source has not been started yet by any client, starts it. 118 status_t start(int clientId, MetaData *params); 119 120 // Stops the real source after all clients have called stop(). 121 status_t stop(int clientId); 122 123 // returns the real source's getFormat(). 124 sp<MetaData> getFormat(int clientId); 125 126 // If the client's desired buffer has already been read into 127 // mLastReadMediaBuffer, points the buffer to that. Otherwise if it is the 128 // master client, reads the buffer from source or else waits for the master 129 // client to read the buffer and uses that. 130 status_t read(int clientId, 131 MediaBuffer **buffer, const MediaSource::ReadOptions *options = NULL); 132 133 // Not implemented right now. 134 status_t pause(int clientId); 135 136 // Function which reads a buffer from the real source into 137 // mLastReadMediaBuffer 138 void readFromSource_lock(const MediaSource::ReadOptions *options); 139 140 // Waits until read from the real source has been completed. 141 // _lock means that the function should be called when the thread has already 142 // obtained the lock for the mutex mLock. 143 void waitForReadFromSource_lock(int32_t clientId); 144 145 // Waits until all clients have read the current buffer in 146 // mLastReadCompleted. 147 void waitForAllClientsLastRead_lock(int32_t clientId); 148 149 // Each client calls this after it completes its read(). Once all clients 150 // have called this for the current buffer, the function calls 151 // mAllReadsCompleteCondition.broadcast() to signal the waiting clients. 152 void signalReadComplete_lock(bool readAborted); 153 154 // Make these constructors private. 155 MediaSourceSplitter(); 156 MediaSourceSplitter(const MediaSourceSplitter &); 157 MediaSourceSplitter &operator=(const MediaSourceSplitter &); 158 159 // This class implements the MediaSource interface. Each client stores a 160 // reference to the parent MediaSourceSplitter and uses it to complete the 161 // various calls. 162 class Client : public MediaSource { 163 public: 164 // Constructor stores reference to the parent MediaSourceSplitter and it 165 // client id. 166 Client(sp<MediaSourceSplitter> splitter, int32_t clientId); 167 168 // MediaSource interface 169 virtual status_t start(MetaData *params = NULL); 170 171 virtual status_t stop(); 172 173 virtual sp<MetaData> getFormat(); 174 175 virtual status_t read( 176 MediaBuffer **buffer, const ReadOptions *options = NULL); 177 178 virtual status_t pause(); 179 180 private: 181 // Refernce to the parent MediaSourceSplitter 182 sp<MediaSourceSplitter> mSplitter; 183 184 // Id of this client. 185 int32_t mClientId; 186 }; 187 188 friend class Client; 189 }; 190 191 } // namespace android 192 193 #endif // MEDIA_SOURCE_SPLITTER_H_ 194