diff options
author | Andreas Huber <andih@google.com> | 2010-11-24 10:58:46 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-11-24 10:58:46 -0800 |
commit | 91a822eb44e7d70f92954304c5d574bb7350bcfd (patch) | |
tree | 92cc59e8f5a4c9e20848f2b7893d7e91d6c23735 /media/libstagefright | |
parent | 841af895d7f5051b9e96899710dba8d3fe2af1f2 (diff) | |
parent | e2b1028852120bcfded33b8f06f66b780437fe92 (diff) | |
download | frameworks_av-91a822eb44e7d70f92954304c5d574bb7350bcfd.zip frameworks_av-91a822eb44e7d70f92954304c5d574bb7350bcfd.tar.gz frameworks_av-91a822eb44e7d70f92954304c5d574bb7350bcfd.tar.bz2 |
Merge "Support streaming data across binder boundaries."
Diffstat (limited to 'media/libstagefright')
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 227 | ||||
-rw-r--r-- | media/libstagefright/include/AwesomePlayer.h | 2 |
2 files changed, 225 insertions, 4 deletions
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index ec58919..a804866 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -34,13 +34,16 @@ #include "UDPPusher.h" #include <binder/IPCThreadState.h> +#include <binder/MemoryDealer.h> +#include <media/IStreamSource.h> +#include <media/stagefright/foundation/hexdump.h> +#include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/AudioPlayer.h> #include <media/stagefright/DataSource.h> #include <media/stagefright/FileSource.h> #include <media/stagefright/MediaBuffer.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaExtractor.h> -#include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaSource.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/OMXCodec.h> @@ -155,6 +158,201 @@ private: const AwesomeNativeWindowRenderer &); }; +//////////////////////////////////////////////////////////////////////////////// + +struct QueueDataSource; + +struct QueueListener : public BnStreamListener { + QueueListener(QueueDataSource *owner) + : mOwner(owner) { + } + + void clearOwner(); + + virtual void queueBuffer(size_t index, size_t size); + virtual void queueCommand(Command cmd); + +private: + Mutex mLock; + + QueueDataSource *mOwner; + + DISALLOW_EVIL_CONSTRUCTORS(QueueListener); +}; + +struct QueueDataSource : public DataSource { + QueueDataSource(const sp<IStreamSource> &source); + + virtual status_t initCheck() const; + + virtual ssize_t readAt(off64_t offset, void *data, size_t size); + + virtual void queueBuffer(size_t index, size_t size); + virtual void queueCommand(IStreamListener::Command cmd); + +protected: + virtual ~QueueDataSource(); + +private: + enum { + kNumBuffers = 16 + }; + + struct BufferInfo { + size_t mIndex; + size_t mOffset; + size_t mSize; + }; + + Mutex mLock; + Condition mCondition; + + sp<IStreamSource> mSource; + sp<QueueListener> mListener; + sp<MemoryDealer> mDealer; + Vector<sp<IMemory> > mBuffers; + + List<BufferInfo> mFilledBuffers; + + off64_t mPosition; + bool mEOS; + + DISALLOW_EVIL_CONSTRUCTORS(QueueDataSource); +}; + +QueueDataSource::QueueDataSource(const sp<IStreamSource> &source) + : mSource(source), + mPosition(0), + mEOS(false) { + mListener = new QueueListener(this); + mSource->setListener(mListener); + + static const size_t kBufferSize = 8192; + + mDealer = new MemoryDealer(kNumBuffers * kBufferSize); + for (size_t i = 0; i < kNumBuffers; ++i) { + sp<IMemory> mem = mDealer->allocate(kBufferSize); + CHECK(mem != NULL); + + mBuffers.push(mem); + } + mSource->setBuffers(mBuffers); + + for (size_t i = 0; i < kNumBuffers; ++i) { + mSource->onBufferAvailable(i); + } +} + +QueueDataSource::~QueueDataSource() { + Mutex::Autolock autoLock(mLock); + + while (mFilledBuffers.size() < kNumBuffers && !mEOS) { + mCondition.wait(mLock); + } + + mListener->clearOwner(); +} + +status_t QueueDataSource::initCheck() const { + return OK; +} + +ssize_t QueueDataSource::readAt(off64_t offset, void *data, size_t size) { + if (offset != mPosition) { + return -EPIPE; + } + + Mutex::Autolock autoLock(mLock); + + size_t sizeDone = 0; + + while (sizeDone < size) { + while (mFilledBuffers.empty() && !mEOS) { + mCondition.wait(mLock); + } + + if (mFilledBuffers.empty()) { + if (sizeDone > 0) { + mPosition += sizeDone; + return sizeDone; + } + return ERROR_END_OF_STREAM; + } + + BufferInfo &info = *mFilledBuffers.begin(); + + size_t copy = size - sizeDone; + if (copy > info.mSize) { + copy = info.mSize; + } + + memcpy((uint8_t *)data + sizeDone, + (const uint8_t *)mBuffers.itemAt(info.mIndex)->pointer() + + info.mOffset, + copy); + + info.mSize -= copy; + info.mOffset += copy; + sizeDone += copy; + + if (info.mSize == 0) { + mSource->onBufferAvailable(info.mIndex); + mFilledBuffers.erase(mFilledBuffers.begin()); + } + } + + mPosition += sizeDone; + + return sizeDone; +} + +void QueueDataSource::queueBuffer(size_t index, size_t size) { + Mutex::Autolock autoLock(mLock); + + CHECK_LT(index, mBuffers.size()); + CHECK_LE(size, mBuffers.itemAt(index)->size()); + + BufferInfo info; + info.mIndex = index; + info.mSize = size; + info.mOffset = 0; + + mFilledBuffers.push_back(info); + mCondition.signal(); +} + +void QueueDataSource::queueCommand(IStreamListener::Command cmd) { + Mutex::Autolock autoLock(mLock); + + if (cmd == IStreamListener::EOS) { + mEOS = true; + mCondition.signal(); + } +} + +void QueueListener::clearOwner() { + Mutex::Autolock autoLock(mLock); + mOwner = NULL; +} + +void QueueListener::queueBuffer(size_t index, size_t size) { + Mutex::Autolock autoLock(mLock); + if (mOwner == NULL) { + return; + } + mOwner->queueBuffer(index, size); +} + +void QueueListener::queueCommand(Command cmd) { + Mutex::Autolock autoLock(mLock); + if (mOwner == NULL) { + return; + } + mOwner->queueCommand(cmd); +} + +//////////////////////////////////////////////////////////////////////////////// + AwesomePlayer::AwesomePlayer() : mQueueStarted(false), mTimeSource(NULL), @@ -164,7 +362,7 @@ AwesomePlayer::AwesomePlayer() mExtractorFlags(0), mVideoBuffer(NULL), mDecryptHandle(NULL) { - CHECK_EQ(mClient.connect(), OK); + CHECK_EQ(mClient.connect(), (status_t)OK); DataSource::RegisterDefaultSniffers(); @@ -264,6 +462,26 @@ status_t AwesomePlayer::setDataSource( return setDataSource_l(dataSource); } +status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) { + Mutex::Autolock autoLock(mLock); + + reset_l(); + + sp<DataSource> dataSource = new QueueDataSource(source); + +#if 0 + sp<MediaExtractor> extractor = + MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); + + return setDataSource_l(extractor); +#else + sp<NuCachedSource2> cached = new NuCachedSource2(dataSource); + dataSource = cached; + + return setDataSource_l(dataSource); +#endif +} + status_t AwesomePlayer::setDataSource_l( const sp<DataSource> &dataSource) { sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); @@ -619,7 +837,8 @@ void AwesomePlayer::partial_reset_l() { IPCThreadState::self()->flushCommands(); } - CHECK_EQ(OK, initVideoDecoder(OMXCodec::kIgnoreCodecSpecificData)); + CHECK_EQ((status_t)OK, + initVideoDecoder(OMXCodec::kIgnoreCodecSpecificData)); } void AwesomePlayer::onStreamDone() { @@ -1171,7 +1390,7 @@ void AwesomePlayer::onVideoEvent() { options.clearSeekTo(); if (err != OK) { - CHECK_EQ(mVideoBuffer, NULL); + CHECK(mVideoBuffer == NULL); if (err == INFO_FORMAT_CHANGED) { LOGV("VideoSource signalled format change."); diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index e33f467..46f4a35 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -67,6 +67,8 @@ struct AwesomePlayer { status_t setDataSource(int fd, int64_t offset, int64_t length); + status_t setDataSource(const sp<IStreamSource> &source); + void reset(); status_t prepare(); |