summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/stagefright/MediaSourceSplitter.h193
-rw-r--r--media/libstagefright/Android.mk1
-rw-r--r--media/libstagefright/MediaSourceSplitter.cpp234
3 files changed, 0 insertions, 428 deletions
diff --git a/include/media/stagefright/MediaSourceSplitter.h b/include/media/stagefright/MediaSourceSplitter.h
deleted file mode 100644
index 568f4c2..0000000
--- a/include/media/stagefright/MediaSourceSplitter.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This class provides a way to split a single media source into multiple sources.
-// The constructor takes in the real mediaSource and createClient() can then be
-// used to create multiple sources served from this real mediaSource.
-//
-// Usage:
-// - Create MediaSourceSplitter by passing in a real mediaSource from which
-// multiple duplicate channels are needed.
-// - Create a client using createClient() and use it as any other mediaSource.
-//
-// Note that multiple clients can be created using createClient() and
-// started/stopped in any order. MediaSourceSplitter stops the real source only
-// when all clients have been stopped.
-//
-// If a new client is created/started after some existing clients have already
-// started, the new client will start getting its read frames from the current
-// time.
-
-#ifndef MEDIA_SOURCE_SPLITTER_H_
-
-#define MEDIA_SOURCE_SPLITTER_H_
-
-#include <media/stagefright/MediaSource.h>
-#include <utils/threads.h>
-#include <utils/Vector.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-class MediaBuffer;
-class MetaData;
-
-class MediaSourceSplitter : public RefBase {
-public:
- // Constructor
- // mediaSource: The real mediaSource. The class keeps a reference to it to
- // implement the various clients.
- MediaSourceSplitter(sp<MediaSource> mediaSource);
-
- ~MediaSourceSplitter();
-
- // Creates a new client of base type MediaSource. Multiple clients can be
- // created which get their data through the same real mediaSource. These
- // clients can then be used like any other MediaSource, all of which provide
- // data from the same real source.
- sp<MediaSource> createClient();
-
-private:
- // Total number of clients created through createClient().
- int32_t mNumberOfClients;
-
- // reference to the real MediaSource passed to the constructor.
- sp<MediaSource> mSource;
-
- // Stores pointer to the MediaBuffer read from the real MediaSource.
- // All clients use this to implement the read() call.
- MediaBuffer *mLastReadMediaBuffer;
-
- // Status code for read from the real MediaSource. All clients return
- // this for their read().
- status_t mLastReadStatus;
-
- // Boolean telling whether the real MediaSource has started.
- bool mSourceStarted;
-
- // List of booleans, one for each client, storing whether the corresponding
- // client's start() has been called.
- Vector<bool> mClientsStarted;
-
- // Stores the number of clients which are currently started.
- int32_t mNumberOfClientsStarted;
-
- // Since different clients call read() asynchronously, we need to keep track
- // of what data is currently read into the mLastReadMediaBuffer.
- // mCurrentReadBit stores the bit for the current read buffer. This bit
- // flips each time a new buffer is read from the source.
- // mClientsDesiredReadBit stores the bit for the next desired read buffer
- // for each client. This bit flips each time read() is completed for this
- // client.
- bool mCurrentReadBit;
- Vector<bool> mClientsDesiredReadBit;
-
- // Number of clients whose current read has been completed.
- int32_t mNumberOfCurrentReads;
-
- // Boolean telling whether the last read has been completed for all clients.
- // The variable is reset to false each time buffer is read from the real
- // source.
- bool mLastReadCompleted;
-
- // A global mutex for access to critical sections.
- Mutex mLock;
-
- // Condition variable for waiting on read from source to complete.
- Condition mReadFromSourceCondition;
-
- // Condition variable for waiting on all client's last read to complete.
- Condition mAllReadsCompleteCondition;
-
- // Functions used by Client to implement the MediaSource interface.
-
- // If the real source has not been started yet by any client, starts it.
- status_t start(int clientId, MetaData *params);
-
- // Stops the real source after all clients have called stop().
- status_t stop(int clientId);
-
- // returns the real source's getFormat().
- sp<MetaData> getFormat(int clientId);
-
- // If the client's desired buffer has already been read into
- // mLastReadMediaBuffer, points the buffer to that. Otherwise if it is the
- // master client, reads the buffer from source or else waits for the master
- // client to read the buffer and uses that.
- status_t read(int clientId,
- MediaBuffer **buffer, const MediaSource::ReadOptions *options = NULL);
-
- // Not implemented right now.
- status_t pause(int clientId);
-
- // Function which reads a buffer from the real source into
- // mLastReadMediaBuffer
- void readFromSource_lock(const MediaSource::ReadOptions *options);
-
- // Waits until read from the real source has been completed.
- // _lock means that the function should be called when the thread has already
- // obtained the lock for the mutex mLock.
- void waitForReadFromSource_lock(int32_t clientId);
-
- // Waits until all clients have read the current buffer in
- // mLastReadCompleted.
- void waitForAllClientsLastRead_lock(int32_t clientId);
-
- // Each client calls this after it completes its read(). Once all clients
- // have called this for the current buffer, the function calls
- // mAllReadsCompleteCondition.broadcast() to signal the waiting clients.
- void signalReadComplete_lock(bool readAborted);
-
- // Make these constructors private.
- MediaSourceSplitter();
- MediaSourceSplitter(const MediaSourceSplitter &);
- MediaSourceSplitter &operator=(const MediaSourceSplitter &);
-
- // This class implements the MediaSource interface. Each client stores a
- // reference to the parent MediaSourceSplitter and uses it to complete the
- // various calls.
- class Client : public MediaSource {
- public:
- // Constructor stores reference to the parent MediaSourceSplitter and it
- // client id.
- Client(sp<MediaSourceSplitter> splitter, int32_t clientId);
-
- // MediaSource interface
- virtual status_t start(MetaData *params = NULL);
-
- virtual status_t stop();
-
- virtual sp<MetaData> getFormat();
-
- virtual status_t read(
- MediaBuffer **buffer, const ReadOptions *options = NULL);
-
- virtual status_t pause();
-
- private:
- // Refernce to the parent MediaSourceSplitter
- sp<MediaSourceSplitter> mSplitter;
-
- // Id of this client.
- int32_t mClientId;
- };
-
- friend class Client;
-};
-
-} // namespace android
-
-#endif // MEDIA_SOURCE_SPLITTER_H_
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 21d6866..5aea8d0 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -34,7 +34,6 @@ LOCAL_SRC_FILES:= \
MediaDefs.cpp \
MediaExtractor.cpp \
MediaSource.cpp \
- MediaSourceSplitter.cpp \
MetaData.cpp \
NuCachedSource2.cpp \
NuMediaExtractor.cpp \
diff --git a/media/libstagefright/MediaSourceSplitter.cpp b/media/libstagefright/MediaSourceSplitter.cpp
deleted file mode 100644
index 3b64ded..0000000
--- a/media/libstagefright/MediaSourceSplitter.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaSourceSplitter"
-#include <utils/Log.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaSourceSplitter.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-MediaSourceSplitter::MediaSourceSplitter(sp<MediaSource> mediaSource) {
- mNumberOfClients = 0;
- mSource = mediaSource;
- mSourceStarted = false;
-
- mNumberOfClientsStarted = 0;
- mNumberOfCurrentReads = 0;
- mCurrentReadBit = 0;
- mLastReadCompleted = true;
-}
-
-MediaSourceSplitter::~MediaSourceSplitter() {
-}
-
-sp<MediaSource> MediaSourceSplitter::createClient() {
- Mutex::Autolock autoLock(mLock);
-
- sp<MediaSource> client = new Client(this, mNumberOfClients++);
- mClientsStarted.push(false);
- mClientsDesiredReadBit.push(0);
- return client;
-}
-
-status_t MediaSourceSplitter::start(int clientId, MetaData *params) {
- Mutex::Autolock autoLock(mLock);
-
- ALOGV("start client (%d)", clientId);
- if (mClientsStarted[clientId]) {
- return OK;
- }
-
- mNumberOfClientsStarted++;
-
- if (!mSourceStarted) {
- ALOGV("Starting real source from client (%d)", clientId);
- status_t err = mSource->start(params);
-
- if (err == OK) {
- mSourceStarted = true;
- mClientsStarted.editItemAt(clientId) = true;
- mClientsDesiredReadBit.editItemAt(clientId) = !mCurrentReadBit;
- }
-
- return err;
- } else {
- mClientsStarted.editItemAt(clientId) = true;
- if (mLastReadCompleted) {
- // Last read was completed. So join in the threads for the next read.
- mClientsDesiredReadBit.editItemAt(clientId) = !mCurrentReadBit;
- } else {
- // Last read is ongoing. So join in the threads for the current read.
- mClientsDesiredReadBit.editItemAt(clientId) = mCurrentReadBit;
- }
- return OK;
- }
-}
-
-status_t MediaSourceSplitter::stop(int clientId) {
- Mutex::Autolock autoLock(mLock);
-
- ALOGV("stop client (%d)", clientId);
- CHECK(clientId >= 0 && clientId < mNumberOfClients);
- CHECK(mClientsStarted[clientId]);
-
- if (--mNumberOfClientsStarted == 0) {
- ALOGV("Stopping real source from client (%d)", clientId);
- status_t err = mSource->stop();
- mSourceStarted = false;
- mClientsStarted.editItemAt(clientId) = false;
- return err;
- } else {
- mClientsStarted.editItemAt(clientId) = false;
- if (!mLastReadCompleted && (mClientsDesiredReadBit[clientId] == mCurrentReadBit)) {
- // !mLastReadCompleted implies that buffer has been read from source, but all
- // clients haven't read it.
- // mClientsDesiredReadBit[clientId] == mCurrentReadBit implies that this
- // client would have wanted to read from this buffer. (i.e. it has not yet
- // called read() for the current read buffer.)
- // Since other threads may be waiting for all the clients' reads to complete,
- // signal that this read has been aborted.
- signalReadComplete_lock(true);
- }
- return OK;
- }
-}
-
-sp<MetaData> MediaSourceSplitter::getFormat(int clientId) {
- Mutex::Autolock autoLock(mLock);
-
- ALOGV("getFormat client (%d)", clientId);
- return mSource->getFormat();
-}
-
-status_t MediaSourceSplitter::read(int clientId,
- MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
- Mutex::Autolock autoLock(mLock);
-
- CHECK(clientId >= 0 && clientId < mNumberOfClients);
-
- ALOGV("read client (%d)", clientId);
- *buffer = NULL;
-
- if (!mClientsStarted[clientId]) {
- return OK;
- }
-
- if (mCurrentReadBit != mClientsDesiredReadBit[clientId]) {
- // Desired buffer has not been read from source yet.
-
- // If the current client is the special client with clientId = 0
- // then read from source, else wait until the client 0 has finished
- // reading from source.
- if (clientId == 0) {
- // Wait for all client's last read to complete first so as to not
- // corrupt the buffer at mLastReadMediaBuffer.
- waitForAllClientsLastRead_lock(clientId);
-
- readFromSource_lock(options);
- *buffer = mLastReadMediaBuffer;
- } else {
- waitForReadFromSource_lock(clientId);
-
- *buffer = mLastReadMediaBuffer;
- (*buffer)->add_ref();
- }
- CHECK(mCurrentReadBit == mClientsDesiredReadBit[clientId]);
- } else {
- // Desired buffer has already been read from source. Use the cached data.
- CHECK(clientId != 0);
-
- *buffer = mLastReadMediaBuffer;
- (*buffer)->add_ref();
- }
-
- mClientsDesiredReadBit.editItemAt(clientId) = !mClientsDesiredReadBit[clientId];
- signalReadComplete_lock(false);
-
- return mLastReadStatus;
-}
-
-void MediaSourceSplitter::readFromSource_lock(const MediaSource::ReadOptions *options) {
- mLastReadStatus = mSource->read(&mLastReadMediaBuffer , options);
-
- mCurrentReadBit = !mCurrentReadBit;
- mLastReadCompleted = false;
- mReadFromSourceCondition.broadcast();
-}
-
-void MediaSourceSplitter::waitForReadFromSource_lock(int32_t clientId) {
- mReadFromSourceCondition.wait(mLock);
-}
-
-void MediaSourceSplitter::waitForAllClientsLastRead_lock(int32_t clientId) {
- if (mLastReadCompleted) {
- return;
- }
- mAllReadsCompleteCondition.wait(mLock);
- CHECK(mLastReadCompleted);
-}
-
-void MediaSourceSplitter::signalReadComplete_lock(bool readAborted) {
- if (!readAborted) {
- mNumberOfCurrentReads++;
- }
-
- if (mNumberOfCurrentReads == mNumberOfClientsStarted) {
- mLastReadCompleted = true;
- mNumberOfCurrentReads = 0;
- mAllReadsCompleteCondition.broadcast();
- }
-}
-
-status_t MediaSourceSplitter::pause(int clientId) {
- return ERROR_UNSUPPORTED;
-}
-
-// Client
-
-MediaSourceSplitter::Client::Client(
- sp<MediaSourceSplitter> splitter,
- int32_t clientId) {
- mSplitter = splitter;
- mClientId = clientId;
-}
-
-status_t MediaSourceSplitter::Client::start(MetaData *params) {
- return mSplitter->start(mClientId, params);
-}
-
-status_t MediaSourceSplitter::Client::stop() {
- return mSplitter->stop(mClientId);
-}
-
-sp<MetaData> MediaSourceSplitter::Client::getFormat() {
- return mSplitter->getFormat(mClientId);
-}
-
-status_t MediaSourceSplitter::Client::read(
- MediaBuffer **buffer, const ReadOptions *options) {
- return mSplitter->read(mClientId, buffer, options);
-}
-
-status_t MediaSourceSplitter::Client::pause() {
- return mSplitter->pause(mClientId);
-}
-
-} // namespace android