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