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
43namespace android {
44
45class MediaBuffer;
46class MetaData;
47
48class MediaSourceSplitter : public RefBase {
49public:
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
63private:
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