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