diff options
author | Marco Nelissen <marcone@google.com> | 2014-12-04 08:57:56 -0800 |
---|---|---|
committer | Marco Nelissen <marcone@google.com> | 2015-01-26 07:57:39 -0800 |
commit | b7848f1c442bc8c71020957948d1b003a62a25b7 (patch) | |
tree | b0a1dfd418429171c0af5379a1820569775a840b | |
parent | 1ed13b3b443735e7f7b5002954f31741b0b1c572 (diff) | |
download | frameworks_av-b7848f1c442bc8c71020957948d1b003a62a25b7.zip frameworks_av-b7848f1c442bc8c71020957948d1b003a62a25b7.tar.gz frameworks_av-b7848f1c442bc8c71020957948d1b003a62a25b7.tar.bz2 |
Remove MediaPlayerService::decode()
and make SoundPool use MediaCodec for decoding files to PCM.
Bug: 18239054
Change-Id: Ia144fc1bbb0d2787638ee972e2224339b4965310
-rw-r--r-- | include/media/IMediaPlayerService.h | 11 | ||||
-rw-r--r-- | include/media/MediaPlayerInterface.h | 1 | ||||
-rw-r--r-- | include/media/SoundPool.h | 241 | ||||
-rw-r--r-- | include/media/mediaplayer.h | 11 | ||||
-rw-r--r-- | media/libmedia/Android.mk | 2 | ||||
-rw-r--r-- | media/libmedia/IMediaPlayerService.cpp | 107 | ||||
-rw-r--r-- | media/libmedia/SoundPool.cpp | 921 | ||||
-rw-r--r-- | media/libmedia/SoundPoolThread.cpp | 114 | ||||
-rw-r--r-- | media/libmedia/SoundPoolThread.h | 66 | ||||
-rw-r--r-- | media/libmedia/mediaplayer.cpp | 41 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 317 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.h | 83 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp | 13 | ||||
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 5 |
14 files changed, 13 insertions, 1920 deletions
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h index d7e584a..67b599a 100644 --- a/include/media/IMediaPlayerService.h +++ b/include/media/IMediaPlayerService.h @@ -51,17 +51,6 @@ public: virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0; virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0; - virtual status_t decode( - const sp<IMediaHTTPService> &httpService, - const char* url, - uint32_t *pSampleRate, - int* pNumChannels, - audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, size_t *pSize) = 0; - - virtual status_t decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, - int* pNumChannels, audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, size_t *pSize) = 0; virtual sp<IOMX> getOMX() = 0; virtual sp<ICrypto> makeCrypto() = 0; virtual sp<IDrm> makeDrm() = 0; diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 0f38c16..b980421 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -88,7 +88,6 @@ public: virtual ~AudioSink() {} virtual bool ready() const = 0; // audio output is open and ready - virtual bool realtime() const = 0; // audio output is real-time output virtual ssize_t bufferSize() const = 0; virtual ssize_t frameCount() const = 0; virtual ssize_t channelCount() const = 0; diff --git a/include/media/SoundPool.h b/include/media/SoundPool.h deleted file mode 100644 index 5830475..0000000 --- a/include/media/SoundPool.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#ifndef SOUNDPOOL_H_ -#define SOUNDPOOL_H_ - -#include <utils/threads.h> -#include <utils/List.h> -#include <utils/Vector.h> -#include <utils/KeyedVector.h> -#include <media/AudioTrack.h> -#include <binder/MemoryHeapBase.h> -#include <binder/MemoryBase.h> - -namespace android { - -static const int IDLE_PRIORITY = -1; - -// forward declarations -class SoundEvent; -class SoundPoolThread; -class SoundPool; - -// for queued events -class SoundPoolEvent { -public: - SoundPoolEvent(int msg, int arg1=0, int arg2=0) : - mMsg(msg), mArg1(arg1), mArg2(arg2) {} - int mMsg; - int mArg1; - int mArg2; - enum MessageType { INVALID, SAMPLE_LOADED }; -}; - -// callback function prototype -typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user); - -// tracks samples used by application -class Sample : public RefBase { -public: - enum sample_state { UNLOADED, LOADING, READY, UNLOADING }; - Sample(int sampleID, const char* url); - Sample(int sampleID, int fd, int64_t offset, int64_t length); - ~Sample(); - int sampleID() { return mSampleID; } - int numChannels() { return mNumChannels; } - int sampleRate() { return mSampleRate; } - audio_format_t format() { return mFormat; } - size_t size() { return mSize; } - int state() { return mState; } - uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); } - status_t doLoad(); - void startLoad() { mState = LOADING; } - sp<IMemory> getIMemory() { return mData; } - - // hack - void init(int numChannels, int sampleRate, audio_format_t format, size_t size, - sp<IMemory> data ) { - mNumChannels = numChannels; mSampleRate = sampleRate; mFormat = format; mSize = size; - mData = data; } - -private: - void init(); - - size_t mSize; - volatile int32_t mRefCount; - uint16_t mSampleID; - uint16_t mSampleRate; - uint8_t mState : 3; - uint8_t mNumChannels : 2; - audio_format_t mFormat; - int mFd; - int64_t mOffset; - int64_t mLength; - char* mUrl; - sp<IMemory> mData; - sp<MemoryHeapBase> mHeap; -}; - -// stores pending events for stolen channels -class SoundEvent -{ -public: - SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0), - mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {} - void set(const sp<Sample>& sample, int channelID, float leftVolume, - float rightVolume, int priority, int loop, float rate); - sp<Sample> sample() { return mSample; } - int channelID() { return mChannelID; } - float leftVolume() { return mLeftVolume; } - float rightVolume() { return mRightVolume; } - int priority() { return mPriority; } - int loop() { return mLoop; } - float rate() { return mRate; } - void clear() { mChannelID = 0; mSample.clear(); } - -protected: - sp<Sample> mSample; - int mChannelID; - float mLeftVolume; - float mRightVolume; - int mPriority; - int mLoop; - float mRate; -}; - -// for channels aka AudioTracks -class SoundChannel : public SoundEvent { -public: - enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING }; - SoundChannel() : mState(IDLE), mNumChannels(1), - mPos(0), mToggle(0), mAutoPaused(false) {} - ~SoundChannel(); - void init(SoundPool* soundPool); - void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume, - int priority, int loop, float rate); - void setVolume_l(float leftVolume, float rightVolume); - void setVolume(float leftVolume, float rightVolume); - void stop_l(); - void stop(); - void pause(); - void autoPause(); - void resume(); - void autoResume(); - void setRate(float rate); - int state() { return mState; } - void setPriority(int priority) { mPriority = priority; } - void setLoop(int loop); - int numChannels() { return mNumChannels; } - void clearNextEvent() { mNextEvent.clear(); } - void nextEvent(); - int nextChannelID() { return mNextEvent.channelID(); } - void dump(); - -private: - static void callback(int event, void* user, void *info); - void process(int event, void *info, unsigned long toggle); - bool doStop_l(); - - SoundPool* mSoundPool; - sp<AudioTrack> mAudioTrack; - SoundEvent mNextEvent; - Mutex mLock; - int mState; - int mNumChannels; - int mPos; - int mAudioBufferSize; - unsigned long mToggle; - bool mAutoPaused; -}; - -// application object for managing a pool of sounds -class SoundPool { - friend class SoundPoolThread; - friend class SoundChannel; -public: - SoundPool(int maxChannels, const audio_attributes_t* pAttributes); - ~SoundPool(); - int load(const char* url, int priority); - int load(int fd, int64_t offset, int64_t length, int priority); - bool unload(int sampleID); - int play(int sampleID, float leftVolume, float rightVolume, int priority, - int loop, float rate); - void pause(int channelID); - void autoPause(); - void resume(int channelID); - void autoResume(); - void stop(int channelID); - void setVolume(int channelID, float leftVolume, float rightVolume); - void setPriority(int channelID, int priority); - void setLoop(int channelID, int loop); - void setRate(int channelID, float rate); - const audio_attributes_t* attributes() { return &mAttributes; } - - // called from SoundPoolThread - void sampleLoaded(int sampleID); - - // called from AudioTrack thread - void done_l(SoundChannel* channel); - - // callback function - void setCallback(SoundPoolCallback* callback, void* user); - void* getUserData() { return mUserData; } - -private: - SoundPool() {} // no default constructor - bool startThreads(); - void doLoad(sp<Sample>& sample); - sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); } - SoundChannel* findChannel (int channelID); - SoundChannel* findNextChannel (int channelID); - SoundChannel* allocateChannel_l(int priority); - void moveToFront_l(SoundChannel* channel); - void notify(SoundPoolEvent event); - void dump(); - - // restart thread - void addToRestartList(SoundChannel* channel); - void addToStopList(SoundChannel* channel); - static int beginThread(void* arg); - int run(); - void quit(); - - Mutex mLock; - Mutex mRestartLock; - Condition mCondition; - SoundPoolThread* mDecodeThread; - SoundChannel* mChannelPool; - List<SoundChannel*> mChannels; - List<SoundChannel*> mRestart; - List<SoundChannel*> mStop; - DefaultKeyedVector< int, sp<Sample> > mSamples; - int mMaxChannels; - audio_attributes_t mAttributes; - int mAllocated; - int mNextSampleID; - int mNextChannelID; - bool mQuit; - - // callback - Mutex mCallbackLock; - SoundPoolCallback* mCallback; - void* mUserData; -}; - -} // end namespace android - -#endif /*SOUNDPOOL_H_*/ diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index 9cc208e..5830933 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -232,17 +232,6 @@ public: bool isLooping(); status_t setVolume(float leftVolume, float rightVolume); void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL); - static status_t decode( - const sp<IMediaHTTPService> &httpService, - const char* url, - uint32_t *pSampleRate, - int* pNumChannels, - audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, - size_t *pSize); - static status_t decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, - int* pNumChannels, audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, size_t *pSize); status_t invoke(const Parcel& request, Parcel *reply); status_t setMetadataFilter(const Parcel& filter); status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata); diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index df6eb57..b91b7d1 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -58,8 +58,6 @@ LOCAL_SRC_FILES:= \ AudioEffect.cpp \ Visualizer.cpp \ MemoryLeakTrackUtil.cpp \ - SoundPool.cpp \ - SoundPoolThread.cpp \ StringArray.cpp LOCAL_SRC_FILES += ../libnbaio/roundup.c diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp index 4d33d40..feea267 100644 --- a/media/libmedia/IMediaPlayerService.cpp +++ b/media/libmedia/IMediaPlayerService.cpp @@ -39,8 +39,6 @@ namespace android { enum { CREATE = IBinder::FIRST_CALL_TRANSACTION, - DECODE_URL, - DECODE_FD, CREATE_MEDIA_RECORDER, CREATE_METADATA_RETRIEVER, GET_OMX, @@ -88,59 +86,6 @@ public: return interface_cast<IMediaRecorder>(reply.readStrongBinder()); } - virtual status_t decode( - const sp<IMediaHTTPService> &httpService, - const char* url, - uint32_t *pSampleRate, - int* pNumChannels, - audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, - size_t *pSize) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); - data.writeInt32(httpService != NULL); - if (httpService != NULL) { - data.writeStrongBinder(IInterface::asBinder(httpService)); - } - data.writeCString(url); - data.writeStrongBinder(IInterface::asBinder(heap)); - status_t status = remote()->transact(DECODE_URL, data, &reply); - if (status == NO_ERROR) { - status = (status_t)reply.readInt32(); - if (status == NO_ERROR) { - *pSampleRate = uint32_t(reply.readInt32()); - *pNumChannels = reply.readInt32(); - *pFormat = (audio_format_t)reply.readInt32(); - *pSize = (size_t)reply.readInt32(); - } - } - return status; - } - - virtual status_t decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, - int* pNumChannels, audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, size_t *pSize) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); - data.writeFileDescriptor(fd); - data.writeInt64(offset); - data.writeInt64(length); - data.writeStrongBinder(IInterface::asBinder(heap)); - status_t status = remote()->transact(DECODE_FD, data, &reply); - if (status == NO_ERROR) { - status = (status_t)reply.readInt32(); - if (status == NO_ERROR) { - *pSampleRate = uint32_t(reply.readInt32()); - *pNumChannels = reply.readInt32(); - *pFormat = (audio_format_t)reply.readInt32(); - *pSize = (size_t)reply.readInt32(); - } - } - return status; - } - virtual sp<IOMX> getOMX() { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); @@ -219,58 +164,6 @@ status_t BnMediaPlayerService::onTransact( reply->writeStrongBinder(IInterface::asBinder(player)); return NO_ERROR; } break; - case DECODE_URL: { - CHECK_INTERFACE(IMediaPlayerService, data, reply); - sp<IMediaHTTPService> httpService; - if (data.readInt32()) { - httpService = - interface_cast<IMediaHTTPService>(data.readStrongBinder()); - } - const char* url = data.readCString(); - sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder()); - uint32_t sampleRate; - int numChannels; - audio_format_t format; - size_t size; - status_t status = - decode(httpService, - url, - &sampleRate, - &numChannels, - &format, - heap, - &size); - reply->writeInt32(status); - if (status == NO_ERROR) { - reply->writeInt32(sampleRate); - reply->writeInt32(numChannels); - reply->writeInt32((int32_t)format); - reply->writeInt32((int32_t)size); - } - return NO_ERROR; - } break; - case DECODE_FD: { - CHECK_INTERFACE(IMediaPlayerService, data, reply); - int fd = dup(data.readFileDescriptor()); - int64_t offset = data.readInt64(); - int64_t length = data.readInt64(); - sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder()); - uint32_t sampleRate; - int numChannels; - audio_format_t format; - size_t size; - status_t status = decode(fd, offset, length, &sampleRate, &numChannels, &format, - heap, &size); - ::close(fd); - reply->writeInt32(status); - if (status == NO_ERROR) { - reply->writeInt32(sampleRate); - reply->writeInt32(numChannels); - reply->writeInt32((int32_t)format); - reply->writeInt32((int32_t)size); - } - return NO_ERROR; - } break; case CREATE_MEDIA_RECORDER: { CHECK_INTERFACE(IMediaPlayerService, data, reply); sp<IMediaRecorder> recorder = createMediaRecorder(); diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp deleted file mode 100644 index d2e381b..0000000 --- a/media/libmedia/SoundPool.cpp +++ /dev/null @@ -1,921 +0,0 @@ -/* - * Copyright (C) 2007 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 "SoundPool" - -#include <inttypes.h> - -#include <utils/Log.h> - -#define USE_SHARED_MEM_BUFFER - -#include <media/AudioTrack.h> -#include <media/IMediaHTTPService.h> -#include <media/mediaplayer.h> -#include <media/SoundPool.h> -#include "SoundPoolThread.h" -#include <media/AudioPolicyHelper.h> - -namespace android -{ - -int kDefaultBufferCount = 4; -uint32_t kMaxSampleRate = 48000; -uint32_t kDefaultSampleRate = 44100; -uint32_t kDefaultFrameCount = 1200; -size_t kDefaultHeapSize = 1024 * 1024; // 1MB - - -SoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes) -{ - ALOGV("SoundPool constructor: maxChannels=%d, attr.usage=%d, attr.flags=0x%x, attr.tags=%s", - maxChannels, pAttributes->usage, pAttributes->flags, pAttributes->tags); - - // check limits - mMaxChannels = maxChannels; - if (mMaxChannels < 1) { - mMaxChannels = 1; - } - else if (mMaxChannels > 32) { - mMaxChannels = 32; - } - ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels); - - mQuit = false; - mDecodeThread = 0; - memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t)); - mAllocated = 0; - mNextSampleID = 0; - mNextChannelID = 0; - - mCallback = 0; - mUserData = 0; - - mChannelPool = new SoundChannel[mMaxChannels]; - for (int i = 0; i < mMaxChannels; ++i) { - mChannelPool[i].init(this); - mChannels.push_back(&mChannelPool[i]); - } - - // start decode thread - startThreads(); -} - -SoundPool::~SoundPool() -{ - ALOGV("SoundPool destructor"); - mDecodeThread->quit(); - quit(); - - Mutex::Autolock lock(&mLock); - - mChannels.clear(); - if (mChannelPool) - delete [] mChannelPool; - // clean up samples - ALOGV("clear samples"); - mSamples.clear(); - - if (mDecodeThread) - delete mDecodeThread; -} - -void SoundPool::addToRestartList(SoundChannel* channel) -{ - Mutex::Autolock lock(&mRestartLock); - if (!mQuit) { - mRestart.push_back(channel); - mCondition.signal(); - } -} - -void SoundPool::addToStopList(SoundChannel* channel) -{ - Mutex::Autolock lock(&mRestartLock); - if (!mQuit) { - mStop.push_back(channel); - mCondition.signal(); - } -} - -int SoundPool::beginThread(void* arg) -{ - SoundPool* p = (SoundPool*)arg; - return p->run(); -} - -int SoundPool::run() -{ - mRestartLock.lock(); - while (!mQuit) { - mCondition.wait(mRestartLock); - ALOGV("awake"); - if (mQuit) break; - - while (!mStop.empty()) { - SoundChannel* channel; - ALOGV("Getting channel from stop list"); - List<SoundChannel* >::iterator iter = mStop.begin(); - channel = *iter; - mStop.erase(iter); - mRestartLock.unlock(); - if (channel != 0) { - Mutex::Autolock lock(&mLock); - channel->stop(); - } - mRestartLock.lock(); - if (mQuit) break; - } - - while (!mRestart.empty()) { - SoundChannel* channel; - ALOGV("Getting channel from list"); - List<SoundChannel*>::iterator iter = mRestart.begin(); - channel = *iter; - mRestart.erase(iter); - mRestartLock.unlock(); - if (channel != 0) { - Mutex::Autolock lock(&mLock); - channel->nextEvent(); - } - mRestartLock.lock(); - if (mQuit) break; - } - } - - mStop.clear(); - mRestart.clear(); - mCondition.signal(); - mRestartLock.unlock(); - ALOGV("goodbye"); - return 0; -} - -void SoundPool::quit() -{ - mRestartLock.lock(); - mQuit = true; - mCondition.signal(); - mCondition.wait(mRestartLock); - ALOGV("return from quit"); - mRestartLock.unlock(); -} - -bool SoundPool::startThreads() -{ - createThreadEtc(beginThread, this, "SoundPool"); - if (mDecodeThread == NULL) - mDecodeThread = new SoundPoolThread(this); - return mDecodeThread != NULL; -} - -SoundChannel* SoundPool::findChannel(int channelID) -{ - for (int i = 0; i < mMaxChannels; ++i) { - if (mChannelPool[i].channelID() == channelID) { - return &mChannelPool[i]; - } - } - return NULL; -} - -SoundChannel* SoundPool::findNextChannel(int channelID) -{ - for (int i = 0; i < mMaxChannels; ++i) { - if (mChannelPool[i].nextChannelID() == channelID) { - return &mChannelPool[i]; - } - } - return NULL; -} - -int SoundPool::load(const char* path, int priority __unused) -{ - ALOGV("load: path=%s, priority=%d", path, priority); - Mutex::Autolock lock(&mLock); - sp<Sample> sample = new Sample(++mNextSampleID, path); - mSamples.add(sample->sampleID(), sample); - doLoad(sample); - return sample->sampleID(); -} - -int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused) -{ - ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d", - fd, offset, length, priority); - Mutex::Autolock lock(&mLock); - sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length); - mSamples.add(sample->sampleID(), sample); - doLoad(sample); - return sample->sampleID(); -} - -void SoundPool::doLoad(sp<Sample>& sample) -{ - ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID()); - sample->startLoad(); - mDecodeThread->loadSample(sample->sampleID()); -} - -bool SoundPool::unload(int sampleID) -{ - ALOGV("unload: sampleID=%d", sampleID); - Mutex::Autolock lock(&mLock); - return mSamples.removeItem(sampleID); -} - -int SoundPool::play(int sampleID, float leftVolume, float rightVolume, - int priority, int loop, float rate) -{ - ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", - sampleID, leftVolume, rightVolume, priority, loop, rate); - sp<Sample> sample; - SoundChannel* channel; - int channelID; - - Mutex::Autolock lock(&mLock); - - if (mQuit) { - return 0; - } - // is sample ready? - sample = findSample(sampleID); - if ((sample == 0) || (sample->state() != Sample::READY)) { - ALOGW(" sample %d not READY", sampleID); - return 0; - } - - dump(); - - // allocate a channel - channel = allocateChannel_l(priority); - - // no channel allocated - return 0 - if (!channel) { - ALOGV("No channel allocated"); - return 0; - } - - channelID = ++mNextChannelID; - - ALOGV("play channel %p state = %d", channel, channel->state()); - channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate); - return channelID; -} - -SoundChannel* SoundPool::allocateChannel_l(int priority) -{ - List<SoundChannel*>::iterator iter; - SoundChannel* channel = NULL; - - // allocate a channel - if (!mChannels.empty()) { - iter = mChannels.begin(); - if (priority >= (*iter)->priority()) { - channel = *iter; - mChannels.erase(iter); - ALOGV("Allocated active channel"); - } - } - - // update priority and put it back in the list - if (channel) { - channel->setPriority(priority); - for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) { - if (priority < (*iter)->priority()) { - break; - } - } - mChannels.insert(iter, channel); - } - return channel; -} - -// move a channel from its current position to the front of the list -void SoundPool::moveToFront_l(SoundChannel* channel) -{ - for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) { - if (*iter == channel) { - mChannels.erase(iter); - mChannels.push_front(channel); - break; - } - } -} - -void SoundPool::pause(int channelID) -{ - ALOGV("pause(%d)", channelID); - Mutex::Autolock lock(&mLock); - SoundChannel* channel = findChannel(channelID); - if (channel) { - channel->pause(); - } -} - -void SoundPool::autoPause() -{ - ALOGV("autoPause()"); - Mutex::Autolock lock(&mLock); - for (int i = 0; i < mMaxChannels; ++i) { - SoundChannel* channel = &mChannelPool[i]; - channel->autoPause(); - } -} - -void SoundPool::resume(int channelID) -{ - ALOGV("resume(%d)", channelID); - Mutex::Autolock lock(&mLock); - SoundChannel* channel = findChannel(channelID); - if (channel) { - channel->resume(); - } -} - -void SoundPool::autoResume() -{ - ALOGV("autoResume()"); - Mutex::Autolock lock(&mLock); - for (int i = 0; i < mMaxChannels; ++i) { - SoundChannel* channel = &mChannelPool[i]; - channel->autoResume(); - } -} - -void SoundPool::stop(int channelID) -{ - ALOGV("stop(%d)", channelID); - Mutex::Autolock lock(&mLock); - SoundChannel* channel = findChannel(channelID); - if (channel) { - channel->stop(); - } else { - channel = findNextChannel(channelID); - if (channel) - channel->clearNextEvent(); - } -} - -void SoundPool::setVolume(int channelID, float leftVolume, float rightVolume) -{ - Mutex::Autolock lock(&mLock); - SoundChannel* channel = findChannel(channelID); - if (channel) { - channel->setVolume(leftVolume, rightVolume); - } -} - -void SoundPool::setPriority(int channelID, int priority) -{ - ALOGV("setPriority(%d, %d)", channelID, priority); - Mutex::Autolock lock(&mLock); - SoundChannel* channel = findChannel(channelID); - if (channel) { - channel->setPriority(priority); - } -} - -void SoundPool::setLoop(int channelID, int loop) -{ - ALOGV("setLoop(%d, %d)", channelID, loop); - Mutex::Autolock lock(&mLock); - SoundChannel* channel = findChannel(channelID); - if (channel) { - channel->setLoop(loop); - } -} - -void SoundPool::setRate(int channelID, float rate) -{ - ALOGV("setRate(%d, %f)", channelID, rate); - Mutex::Autolock lock(&mLock); - SoundChannel* channel = findChannel(channelID); - if (channel) { - channel->setRate(rate); - } -} - -// call with lock held -void SoundPool::done_l(SoundChannel* channel) -{ - ALOGV("done_l(%d)", channel->channelID()); - // if "stolen", play next event - if (channel->nextChannelID() != 0) { - ALOGV("add to restart list"); - addToRestartList(channel); - } - - // return to idle state - else { - ALOGV("move to front"); - moveToFront_l(channel); - } -} - -void SoundPool::setCallback(SoundPoolCallback* callback, void* user) -{ - Mutex::Autolock lock(&mCallbackLock); - mCallback = callback; - mUserData = user; -} - -void SoundPool::notify(SoundPoolEvent event) -{ - Mutex::Autolock lock(&mCallbackLock); - if (mCallback != NULL) { - mCallback(event, this, mUserData); - } -} - -void SoundPool::dump() -{ - for (int i = 0; i < mMaxChannels; ++i) { - mChannelPool[i].dump(); - } -} - - -Sample::Sample(int sampleID, const char* url) -{ - init(); - mSampleID = sampleID; - mUrl = strdup(url); - ALOGV("create sampleID=%d, url=%s", mSampleID, mUrl); -} - -Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length) -{ - init(); - mSampleID = sampleID; - mFd = dup(fd); - mOffset = offset; - mLength = length; - ALOGV("create sampleID=%d, fd=%d, offset=%" PRId64 " length=%" PRId64, - mSampleID, mFd, mLength, mOffset); -} - -void Sample::init() -{ - mSize = 0; - mRefCount = 0; - mSampleID = 0; - mState = UNLOADED; - mFd = -1; - mOffset = 0; - mLength = 0; - mUrl = 0; -} - -Sample::~Sample() -{ - ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd); - if (mFd > 0) { - ALOGV("close(%d)", mFd); - ::close(mFd); - } - free(mUrl); -} - -status_t Sample::doLoad() -{ - uint32_t sampleRate; - int numChannels; - audio_format_t format; - status_t status; - mHeap = new MemoryHeapBase(kDefaultHeapSize); - - ALOGV("Start decode"); - if (mUrl) { - status = MediaPlayer::decode( - NULL /* httpService */, - mUrl, - &sampleRate, - &numChannels, - &format, - mHeap, - &mSize); - } else { - status = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format, - mHeap, &mSize); - ALOGV("close(%d)", mFd); - ::close(mFd); - mFd = -1; - } - if (status != NO_ERROR) { - ALOGE("Unable to load sample: %s", mUrl); - goto error; - } - ALOGV("pointer = %p, size = %zu, sampleRate = %u, numChannels = %d", - mHeap->getBase(), mSize, sampleRate, numChannels); - - if (sampleRate > kMaxSampleRate) { - ALOGE("Sample rate (%u) out of range", sampleRate); - status = BAD_VALUE; - goto error; - } - - if ((numChannels < 1) || (numChannels > 2)) { - ALOGE("Sample channel count (%d) out of range", numChannels); - status = BAD_VALUE; - goto error; - } - - mData = new MemoryBase(mHeap, 0, mSize); - mSampleRate = sampleRate; - mNumChannels = numChannels; - mFormat = format; - mState = READY; - return NO_ERROR; - -error: - mHeap.clear(); - return status; -} - - -void SoundChannel::init(SoundPool* soundPool) -{ - mSoundPool = soundPool; -} - -// call with sound pool lock held -void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume, - float rightVolume, int priority, int loop, float rate) -{ - sp<AudioTrack> oldTrack; - sp<AudioTrack> newTrack; - status_t status; - - { // scope for the lock - Mutex::Autolock lock(&mLock); - - ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f," - " priority=%d, loop=%d, rate=%f", - this, sample->sampleID(), nextChannelID, leftVolume, rightVolume, - priority, loop, rate); - - // if not idle, this voice is being stolen - if (mState != IDLE) { - ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID); - mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); - stop_l(); - return; - } - - // initialize track - size_t afFrameCount; - uint32_t afSampleRate; - audio_stream_type_t streamType = audio_attributes_to_stream_type(mSoundPool->attributes()); - if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { - afFrameCount = kDefaultFrameCount; - } - if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { - afSampleRate = kDefaultSampleRate; - } - int numChannels = sample->numChannels(); - uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5); - uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate; - uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount; - size_t frameCount = 0; - - if (loop) { - frameCount = sample->size()/numChannels/ - ((sample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)); - } - -#ifndef USE_SHARED_MEM_BUFFER - // Ensure minimum audio buffer size in case of short looped sample - if(frameCount < totalFrames) { - frameCount = totalFrames; - } -#endif - - // mToggle toggles each time a track is started on a given channel. - // The toggle is concatenated with the SoundChannel address and passed to AudioTrack - // as callback user data. This enables the detection of callbacks received from the old - // audio track while the new one is being started and avoids processing them with - // wrong audio audio buffer size (mAudioBufferSize) - unsigned long toggle = mToggle ^ 1; - void *userData = (void *)((unsigned long)this | toggle); - audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(numChannels); - - // do not create a new audio track if current track is compatible with sample parameters -#ifdef USE_SHARED_MEM_BUFFER - newTrack = new AudioTrack(streamType, sampleRate, sample->format(), - channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData); -#else - newTrack = new AudioTrack(streamType, sampleRate, sample->format(), - channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData, - bufferFrames); -#endif - oldTrack = mAudioTrack; - status = newTrack->initCheck(); - if (status != NO_ERROR) { - ALOGE("Error creating AudioTrack"); - goto exit; - } - ALOGV("setVolume %p", newTrack.get()); - newTrack->setVolume(leftVolume, rightVolume); - newTrack->setLoop(0, frameCount, loop); - - // From now on, AudioTrack callbacks received with previous toggle value will be ignored. - mToggle = toggle; - mAudioTrack = newTrack; - mPos = 0; - mSample = sample; - mChannelID = nextChannelID; - mPriority = priority; - mLoop = loop; - mLeftVolume = leftVolume; - mRightVolume = rightVolume; - mNumChannels = numChannels; - mRate = rate; - clearNextEvent(); - mState = PLAYING; - mAudioTrack->start(); - mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize(); - } - -exit: - ALOGV("delete oldTrack %p", oldTrack.get()); - if (status != NO_ERROR) { - mAudioTrack.clear(); - } -} - -void SoundChannel::nextEvent() -{ - sp<Sample> sample; - int nextChannelID; - float leftVolume; - float rightVolume; - int priority; - int loop; - float rate; - - // check for valid event - { - Mutex::Autolock lock(&mLock); - nextChannelID = mNextEvent.channelID(); - if (nextChannelID == 0) { - ALOGV("stolen channel has no event"); - return; - } - - sample = mNextEvent.sample(); - leftVolume = mNextEvent.leftVolume(); - rightVolume = mNextEvent.rightVolume(); - priority = mNextEvent.priority(); - loop = mNextEvent.loop(); - rate = mNextEvent.rate(); - } - - ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID); - play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); -} - -void SoundChannel::callback(int event, void* user, void *info) -{ - SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1)); - - channel->process(event, info, (unsigned long)user & 1); -} - -void SoundChannel::process(int event, void *info, unsigned long toggle) -{ - //ALOGV("process(%d)", mChannelID); - - Mutex::Autolock lock(&mLock); - - AudioTrack::Buffer* b = NULL; - if (event == AudioTrack::EVENT_MORE_DATA) { - b = static_cast<AudioTrack::Buffer *>(info); - } - - if (mToggle != toggle) { - ALOGV("process wrong toggle %p channel %d", this, mChannelID); - if (b != NULL) { - b->size = 0; - } - return; - } - - sp<Sample> sample = mSample; - -// ALOGV("SoundChannel::process event %d", event); - - if (event == AudioTrack::EVENT_MORE_DATA) { - - // check for stop state - if (b->size == 0) return; - - if (mState == IDLE) { - b->size = 0; - return; - } - - if (sample != 0) { - // fill buffer - uint8_t* q = (uint8_t*) b->i8; - size_t count = 0; - - if (mPos < (int)sample->size()) { - uint8_t* p = sample->data() + mPos; - count = sample->size() - mPos; - if (count > b->size) { - count = b->size; - } - memcpy(q, p, count); -// ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, -// count); - } else if (mPos < mAudioBufferSize) { - count = mAudioBufferSize - mPos; - if (count > b->size) { - count = b->size; - } - memset(q, 0, count); -// ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count); - } - - mPos += count; - b->size = count; - //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]); - } - } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END || - event == AudioTrack::EVENT_NEW_IAUDIOTRACK) { - ALOGV("process %p channel %d event %s", - this, mChannelID, (event == AudioTrack::EVENT_UNDERRUN) ? "UNDERRUN" : - (event == AudioTrack::EVENT_BUFFER_END) ? "BUFFER_END" : "NEW_IAUDIOTRACK"); - mSoundPool->addToStopList(this); - } else if (event == AudioTrack::EVENT_LOOP_END) { - ALOGV("End loop %p channel %d", this, mChannelID); - } else { - ALOGW("SoundChannel::process unexpected event %d", event); - } -} - - -// call with lock held -bool SoundChannel::doStop_l() -{ - if (mState != IDLE) { - setVolume_l(0, 0); - ALOGV("stop"); - mAudioTrack->stop(); - mSample.clear(); - mState = IDLE; - mPriority = IDLE_PRIORITY; - return true; - } - return false; -} - -// call with lock held and sound pool lock held -void SoundChannel::stop_l() -{ - if (doStop_l()) { - mSoundPool->done_l(this); - } -} - -// call with sound pool lock held -void SoundChannel::stop() -{ - bool stopped; - { - Mutex::Autolock lock(&mLock); - stopped = doStop_l(); - } - - if (stopped) { - mSoundPool->done_l(this); - } -} - -//FIXME: Pause is a little broken right now -void SoundChannel::pause() -{ - Mutex::Autolock lock(&mLock); - if (mState == PLAYING) { - ALOGV("pause track"); - mState = PAUSED; - mAudioTrack->pause(); - } -} - -void SoundChannel::autoPause() -{ - Mutex::Autolock lock(&mLock); - if (mState == PLAYING) { - ALOGV("pause track"); - mState = PAUSED; - mAutoPaused = true; - mAudioTrack->pause(); - } -} - -void SoundChannel::resume() -{ - Mutex::Autolock lock(&mLock); - if (mState == PAUSED) { - ALOGV("resume track"); - mState = PLAYING; - mAutoPaused = false; - mAudioTrack->start(); - } -} - -void SoundChannel::autoResume() -{ - Mutex::Autolock lock(&mLock); - if (mAutoPaused && (mState == PAUSED)) { - ALOGV("resume track"); - mState = PLAYING; - mAutoPaused = false; - mAudioTrack->start(); - } -} - -void SoundChannel::setRate(float rate) -{ - Mutex::Autolock lock(&mLock); - if (mAudioTrack != NULL && mSample != 0) { - uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5); - mAudioTrack->setSampleRate(sampleRate); - mRate = rate; - } -} - -// call with lock held -void SoundChannel::setVolume_l(float leftVolume, float rightVolume) -{ - mLeftVolume = leftVolume; - mRightVolume = rightVolume; - if (mAudioTrack != NULL) - mAudioTrack->setVolume(leftVolume, rightVolume); -} - -void SoundChannel::setVolume(float leftVolume, float rightVolume) -{ - Mutex::Autolock lock(&mLock); - setVolume_l(leftVolume, rightVolume); -} - -void SoundChannel::setLoop(int loop) -{ - Mutex::Autolock lock(&mLock); - if (mAudioTrack != NULL && mSample != 0) { - uint32_t loopEnd = mSample->size()/mNumChannels/ - ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)); - mAudioTrack->setLoop(0, loopEnd, loop); - mLoop = loop; - } -} - -SoundChannel::~SoundChannel() -{ - ALOGV("SoundChannel destructor %p", this); - { - Mutex::Autolock lock(&mLock); - clearNextEvent(); - doStop_l(); - } - // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack - // callback thread to exit which may need to execute process() and acquire the mLock. - mAudioTrack.clear(); -} - -void SoundChannel::dump() -{ - ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d", - mState, mChannelID, mNumChannels, mPos, mPriority, mLoop); -} - -void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume, - float rightVolume, int priority, int loop, float rate) -{ - mSample = sample; - mChannelID = channelID; - mLeftVolume = leftVolume; - mRightVolume = rightVolume; - mPriority = priority; - mLoop = loop; - mRate =rate; -} - -} // end namespace android diff --git a/media/libmedia/SoundPoolThread.cpp b/media/libmedia/SoundPoolThread.cpp deleted file mode 100644 index ba3b482..0000000 --- a/media/libmedia/SoundPoolThread.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2007 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 "SoundPoolThread" -#include "utils/Log.h" - -#include "SoundPoolThread.h" - -namespace android { - -void SoundPoolThread::write(SoundPoolMsg msg) { - Mutex::Autolock lock(&mLock); - while (mMsgQueue.size() >= maxMessages) { - mCondition.wait(mLock); - } - - // if thread is quitting, don't add to queue - if (mRunning) { - mMsgQueue.push(msg); - mCondition.signal(); - } -} - -const SoundPoolMsg SoundPoolThread::read() { - Mutex::Autolock lock(&mLock); - while (mMsgQueue.size() == 0) { - mCondition.wait(mLock); - } - SoundPoolMsg msg = mMsgQueue[0]; - mMsgQueue.removeAt(0); - mCondition.signal(); - return msg; -} - -void SoundPoolThread::quit() { - Mutex::Autolock lock(&mLock); - if (mRunning) { - mRunning = false; - mMsgQueue.clear(); - mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0)); - mCondition.signal(); - mCondition.wait(mLock); - } - ALOGV("return from quit"); -} - -SoundPoolThread::SoundPoolThread(SoundPool* soundPool) : - mSoundPool(soundPool) -{ - mMsgQueue.setCapacity(maxMessages); - if (createThreadEtc(beginThread, this, "SoundPoolThread")) { - mRunning = true; - } -} - -SoundPoolThread::~SoundPoolThread() -{ - quit(); -} - -int SoundPoolThread::beginThread(void* arg) { - ALOGV("beginThread"); - SoundPoolThread* soundPoolThread = (SoundPoolThread*)arg; - return soundPoolThread->run(); -} - -int SoundPoolThread::run() { - ALOGV("run"); - for (;;) { - SoundPoolMsg msg = read(); - ALOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData); - switch (msg.mMessageType) { - case SoundPoolMsg::KILL: - ALOGV("goodbye"); - return NO_ERROR; - case SoundPoolMsg::LOAD_SAMPLE: - doLoadSample(msg.mData); - break; - default: - ALOGW("run: Unrecognized message %d\n", - msg.mMessageType); - break; - } - } -} - -void SoundPoolThread::loadSample(int sampleID) { - write(SoundPoolMsg(SoundPoolMsg::LOAD_SAMPLE, sampleID)); -} - -void SoundPoolThread::doLoadSample(int sampleID) { - sp <Sample> sample = mSoundPool->findSample(sampleID); - status_t status = -1; - if (sample != 0) { - status = sample->doLoad(); - } - mSoundPool->notify(SoundPoolEvent(SoundPoolEvent::SAMPLE_LOADED, sampleID, status)); -} - -} // end namespace android diff --git a/media/libmedia/SoundPoolThread.h b/media/libmedia/SoundPoolThread.h deleted file mode 100644 index 7e96900..0000000 --- a/media/libmedia/SoundPoolThread.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#ifndef SOUNDPOOLTHREAD_H_ -#define SOUNDPOOLTHREAD_H_ - -#include <utils/threads.h> -#include <utils/Vector.h> -#include <media/AudioTrack.h> - -#include <media/SoundPool.h> - -namespace android { - -class SoundPoolMsg { -public: - enum MessageType { INVALID, KILL, LOAD_SAMPLE }; - SoundPoolMsg() : mMessageType(INVALID), mData(0) {} - SoundPoolMsg(MessageType MessageType, int data) : - mMessageType(MessageType), mData(data) {} - uint16_t mMessageType; - uint16_t mData; -}; - -/* - * This class handles background requests from the SoundPool - */ -class SoundPoolThread { -public: - SoundPoolThread(SoundPool* SoundPool); - ~SoundPoolThread(); - void loadSample(int sampleID); - void quit(); - void write(SoundPoolMsg msg); - -private: - static const size_t maxMessages = 5; - - static int beginThread(void* arg); - int run(); - void doLoadSample(int sampleID); - const SoundPoolMsg read(); - - Mutex mLock; - Condition mCondition; - Vector<SoundPoolMsg> mMsgQueue; - SoundPool* mSoundPool; - bool mRunning; -}; - -} // end namespace android - -#endif /*SOUNDPOOLTHREAD_H_*/ diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 9611ac7..05c89ed 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -835,53 +835,12 @@ void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj) } } -/*static*/ status_t MediaPlayer::decode( - const sp<IMediaHTTPService> &httpService, - const char* url, - uint32_t *pSampleRate, - int* pNumChannels, - audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, - size_t *pSize) -{ - ALOGV("decode(%s)", url); - status_t status; - const sp<IMediaPlayerService>& service = getMediaPlayerService(); - if (service != 0) { - status = service->decode(httpService, url, pSampleRate, pNumChannels, pFormat, heap, pSize); - } else { - ALOGE("Unable to locate media service"); - status = DEAD_OBJECT; - } - return status; - -} - void MediaPlayer::died() { ALOGV("died"); notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0); } -/*static*/ status_t MediaPlayer::decode(int fd, int64_t offset, int64_t length, - uint32_t *pSampleRate, int* pNumChannels, - audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, size_t *pSize) -{ - ALOGV("decode(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); - status_t status; - const sp<IMediaPlayerService>& service = getMediaPlayerService(); - if (service != 0) { - status = service->decode(fd, offset, length, pSampleRate, - pNumChannels, pFormat, heap, pSize); - } else { - ALOGE("Unable to locate media service"); - status = DEAD_OBJECT; - } - return status; - -} - status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) { if (mPlayer == NULL) { return NO_INIT; diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 4d88a7f..1936218 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -384,28 +384,6 @@ sp<IRemoteDisplay> MediaPlayerService::listenForRemoteDisplay( return new RemoteDisplay(client, iface.string()); } -status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& /*args*/) const -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - result.append(" AudioCache\n"); - if (mHeap != 0) { - snprintf(buffer, 255, " heap base(%p), size(%zu), flags(%d)\n", - mHeap->getBase(), mHeap->getSize(), mHeap->getFlags()); - result.append(buffer); - } - snprintf(buffer, 255, " msec per frame(%f), channel count(%d), format(%d), frame count(%zd)\n", - mMsecsPerFrame, mChannelCount, mFormat, mFrameCount); - result.append(buffer); - snprintf(buffer, 255, " sample rate(%d), size(%d), error(%d), command complete(%s)\n", - mSampleRate, mSize, mError, mCommandComplete?"true":"false"); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const { const size_t SIZE = 256; @@ -1279,128 +1257,6 @@ int Antagonizer::callbackThread(void* user) } #endif -status_t MediaPlayerService::decode( - const sp<IMediaHTTPService> &httpService, - const char* url, - uint32_t *pSampleRate, - int* pNumChannels, - audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, - size_t *pSize) -{ - ALOGV("decode(%s)", url); - sp<MediaPlayerBase> player; - status_t status = BAD_VALUE; - - // Protect our precious, precious DRMd ringtones by only allowing - // decoding of http, but not filesystem paths or content Uris. - // If the application wants to decode those, it should open a - // filedescriptor for them and use that. - if (url != NULL && strncmp(url, "http://", 7) != 0) { - ALOGD("Can't decode %s by path, use filedescriptor instead", url); - return BAD_VALUE; - } - - player_type playerType = - MediaPlayerFactory::getPlayerType(NULL /* client */, url); - ALOGV("player type = %d", playerType); - - // create the right type of player - sp<AudioCache> cache = new AudioCache(heap); - player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify); - if (player == NULL) goto Exit; - if (player->hardwareOutput()) goto Exit; - - static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache); - - // set data source - if (player->setDataSource(httpService, url) != NO_ERROR) goto Exit; - - ALOGV("prepare"); - player->prepareAsync(); - - ALOGV("wait for prepare"); - if (cache->wait() != NO_ERROR) goto Exit; - - ALOGV("start"); - player->start(); - - ALOGV("wait for playback complete"); - cache->wait(); - // in case of error, return what was successfully decoded. - if (cache->size() == 0) { - goto Exit; - } - - *pSize = cache->size(); - *pSampleRate = cache->sampleRate(); - *pNumChannels = cache->channelCount(); - *pFormat = cache->format(); - ALOGV("return size %d sampleRate=%u, channelCount = %d, format = %d", - *pSize, *pSampleRate, *pNumChannels, *pFormat); - status = NO_ERROR; - -Exit: - if (player != 0) player->reset(); - return status; -} - -status_t MediaPlayerService::decode(int fd, int64_t offset, int64_t length, - uint32_t *pSampleRate, int* pNumChannels, - audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, size_t *pSize) -{ - ALOGV("decode(%d, %lld, %lld)", fd, offset, length); - sp<MediaPlayerBase> player; - status_t status = BAD_VALUE; - - player_type playerType = MediaPlayerFactory::getPlayerType(NULL /* client */, - fd, - offset, - length); - ALOGV("player type = %d", playerType); - - // create the right type of player - sp<AudioCache> cache = new AudioCache(heap); - player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify); - if (player == NULL) goto Exit; - if (player->hardwareOutput()) goto Exit; - - static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache); - - // set data source - if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit; - - ALOGV("prepare"); - player->prepareAsync(); - - ALOGV("wait for prepare"); - if (cache->wait() != NO_ERROR) goto Exit; - - ALOGV("start"); - player->start(); - - ALOGV("wait for playback complete"); - cache->wait(); - // in case of error, return what was successfully decoded. - if (cache->size() == 0) { - goto Exit; - } - - *pSize = cache->size(); - *pSampleRate = cache->sampleRate(); - *pNumChannels = cache->channelCount(); - *pFormat = cache->format(); - ALOGV("return size %d, sampleRate=%u, channelCount = %d, format = %d", - *pSize, *pSampleRate, *pNumChannels, *pFormat); - status = NO_ERROR; - -Exit: - if (player != 0) player->reset(); - return status; -} - - #undef LOG_TAG #define LOG_TAG "AudioSink" MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid, int pid, @@ -1950,47 +1806,6 @@ uint32_t MediaPlayerService::AudioOutput::getSampleRate() const return mTrack->getSampleRate(); } -#undef LOG_TAG -#define LOG_TAG "AudioCache" -MediaPlayerService::AudioCache::AudioCache(const sp<IMemoryHeap>& heap) : - mHeap(heap), mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0), - mFrameSize(1), mError(NO_ERROR), mCommandComplete(false) -{ -} - -uint32_t MediaPlayerService::AudioCache::latency () const -{ - return 0; -} - -float MediaPlayerService::AudioCache::msecsPerFrame() const -{ - return mMsecsPerFrame; -} - -status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) const -{ - if (position == 0) return BAD_VALUE; - *position = mSize / mFrameSize; - return NO_ERROR; -} - -status_t MediaPlayerService::AudioCache::getTimestamp(AudioTimestamp &ts) const -{ - ts.mPosition = mSize / mFrameSize; - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - ts.mTime.tv_sec = now / 1000000000LL; - ts.mTime.tv_nsec = now - (1000000000LL * ts.mTime.tv_sec); - return NO_ERROR; -} - -status_t MediaPlayerService::AudioCache::getFramesWritten(uint32_t *written) const -{ - if (written == 0) return BAD_VALUE; - *written = mSize / mFrameSize; - return NO_ERROR; -} - //////////////////////////////////////////////////////////////////////////////// struct CallbackThread : public Thread { @@ -2058,136 +1873,6 @@ bool CallbackThread::threadLoop() { //////////////////////////////////////////////////////////////////////////////// -status_t MediaPlayerService::AudioCache::open( - uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, - audio_format_t format, int bufferCount, - AudioCallback cb, void *cookie, audio_output_flags_t /*flags*/, - const audio_offload_info_t* /*offloadInfo*/) -{ - ALOGV("open(%u, %d, 0x%x, %d, %d)", sampleRate, channelCount, channelMask, format, bufferCount); - if (mHeap->getHeapID() < 0) { - return NO_INIT; - } - - mSampleRate = sampleRate; - mChannelCount = (uint16_t)channelCount; - mFormat = format; - mMsecsPerFrame = 1.e3 / (float) sampleRate; - mFrameSize = audio_is_linear_pcm(mFormat) - ? mChannelCount * audio_bytes_per_sample(mFormat) : 1; - mFrameCount = mHeap->getSize() / mFrameSize; - - if (cb != NULL) { - mCallbackThread = new CallbackThread(this, cb, cookie); - } - return NO_ERROR; -} - -status_t MediaPlayerService::AudioCache::start() { - if (mCallbackThread != NULL) { - mCallbackThread->run("AudioCache callback"); - } - return NO_ERROR; -} - -void MediaPlayerService::AudioCache::stop() { - if (mCallbackThread != NULL) { - mCallbackThread->requestExitAndWait(); - } -} - -ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size) -{ - ALOGV("write(%p, %u)", buffer, size); - if ((buffer == 0) || (size == 0)) return size; - - uint8_t* p = static_cast<uint8_t*>(mHeap->getBase()); - if (p == NULL) return NO_INIT; - p += mSize; - ALOGV("memcpy(%p, %p, %u)", p, buffer, size); - - bool overflow = mSize + size > mHeap->getSize(); - if (overflow) { - ALOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize()); - size = mHeap->getSize() - mSize; - } - size -= size % mFrameSize; // consume only integral amounts of frame size - memcpy(p, buffer, size); - mSize += size; - - if (overflow) { - // Signal heap filled here (last frame may be truncated). - // After this point, no more data should be written as the - // heap is filled and the AudioCache should be effectively - // immutable with respect to future writes. - // - // It is thus safe for another thread to read the AudioCache. - mCommandComplete = true; - mSignal.signal(); - } - return size; -} - -// call with lock held -status_t MediaPlayerService::AudioCache::wait() -{ - Mutex::Autolock lock(mLock); - while (!mCommandComplete) { - mSignal.wait(mLock); - } - mCommandComplete = false; - - if (mError == NO_ERROR) { - ALOGV("wait - success"); - } else { - ALOGV("wait - error"); - } - return mError; -} - -void MediaPlayerService::AudioCache::notify( - void* cookie, int msg, int ext1, int ext2, const Parcel* /*obj*/) -{ - ALOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2); - AudioCache* p = static_cast<AudioCache*>(cookie); - - // ignore buffering messages - switch (msg) - { - case MEDIA_ERROR: - ALOGE("Error %d, %d occurred", ext1, ext2); - p->mError = ext1; - break; - case MEDIA_PREPARED: - ALOGV("prepared"); - break; - case MEDIA_PLAYBACK_COMPLETE: - ALOGV("playback complete"); - break; - default: - ALOGV("ignored"); - return; - } - - // wake up thread - Mutex::Autolock lock(p->mLock); - p->mCommandComplete = true; - p->mSignal.signal(); -} - -int MediaPlayerService::AudioCache::getSessionId() const -{ - return 0; -} - -uint32_t MediaPlayerService::AudioCache::getSampleRate() const -{ - if (mMsecsPerFrame == 0) { - return 0; - } - return (uint32_t)(1.e3 / mMsecsPerFrame); -} - void MediaPlayerService::addBatteryData(uint32_t params) { Mutex::Autolock lock(mLock); @@ -2231,7 +1916,7 @@ void MediaPlayerService::addBatteryData(uint32_t params) return; } - // an sudio stream is started + // an audio stream is started if (params & kBatteryDataAudioFlingerStart) { // record the start time only if currently no other audio // is being played diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 3b96e88..fad3447 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -77,7 +77,6 @@ class MediaPlayerService : public BnMediaPlayerService virtual ~AudioOutput(); virtual bool ready() const { return mTrack != 0; } - virtual bool realtime() const { return true; } virtual ssize_t bufferSize() const; virtual ssize_t frameCount() const; virtual ssize_t channelCount() const; @@ -184,75 +183,6 @@ class MediaPlayerService : public BnMediaPlayerService }; // AudioOutput - class AudioCache : public MediaPlayerBase::AudioSink - { - public: - AudioCache(const sp<IMemoryHeap>& heap); - virtual ~AudioCache() {} - - virtual bool ready() const { return (mChannelCount > 0) && (mHeap->getHeapID() > 0); } - virtual bool realtime() const { return false; } - virtual ssize_t bufferSize() const { return frameSize() * mFrameCount; } - virtual ssize_t frameCount() const { return mFrameCount; } - virtual ssize_t channelCount() const { return (ssize_t)mChannelCount; } - virtual ssize_t frameSize() const { return (ssize_t)mFrameSize; } - virtual uint32_t latency() const; - virtual float msecsPerFrame() const; - virtual status_t getPosition(uint32_t *position) const; - virtual status_t getTimestamp(AudioTimestamp &ts) const; - virtual status_t getFramesWritten(uint32_t *frameswritten) const; - virtual int getSessionId() const; - virtual uint32_t getSampleRate() const; - - virtual status_t open( - uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, - audio_format_t format, int bufferCount = 1, - AudioCallback cb = NULL, void *cookie = NULL, - audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, - const audio_offload_info_t *offloadInfo = NULL); - - virtual status_t start(); - virtual ssize_t write(const void* buffer, size_t size); - virtual void stop(); - virtual void flush() {} - virtual void pause() {} - virtual void close() {} - void setAudioStreamType(audio_stream_type_t streamType __unused) {} - // stream type is not used for AudioCache - virtual audio_stream_type_t getAudioStreamType() const { return AUDIO_STREAM_DEFAULT; } - - void setVolume(float left __unused, float right __unused) {} - virtual status_t setPlaybackRatePermille(int32_t ratePermille __unused) { return INVALID_OPERATION; } - uint32_t sampleRate() const { return mSampleRate; } - audio_format_t format() const { return mFormat; } - size_t size() const { return mSize; } - status_t wait(); - - sp<IMemoryHeap> getHeap() const { return mHeap; } - - static void notify(void* cookie, int msg, - int ext1, int ext2, const Parcel *obj); - virtual status_t dump(int fd, const Vector<String16>& args) const; - - private: - AudioCache(); - - Mutex mLock; - Condition mSignal; - sp<IMemoryHeap> mHeap; - float mMsecsPerFrame; - uint16_t mChannelCount; - audio_format_t mFormat; - ssize_t mFrameCount; - uint32_t mSampleRate; - uint32_t mSize; - size_t mFrameSize; - int mError; - bool mCommandComplete; - - sp<Thread> mCallbackThread; - }; // AudioCache - public: static void instantiate(); @@ -263,19 +193,6 @@ public: virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId); - virtual status_t decode( - const sp<IMediaHTTPService> &httpService, - const char* url, - uint32_t *pSampleRate, - int* pNumChannels, - audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, - size_t *pSize); - - virtual status_t decode(int fd, int64_t offset, int64_t length, - uint32_t *pSampleRate, int* pNumChannels, - audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, size_t *pSize); virtual sp<IMediaCodecList> getCodecList() const; virtual sp<IOMX> getOMX(); virtual sp<ICrypto> makeCrypto(); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 4bff90f..c52d837 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -637,8 +637,17 @@ void NuPlayerDriver::notifyListener_l( case MEDIA_PLAYBACK_COMPLETE: { if (mState != STATE_RESET_IN_PROGRESS) { - if (mLooping || (mAutoLoop - && (mAudioSink == NULL || mAudioSink->realtime()))) { + if (mAutoLoop) { + audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; + if (mAudioSink != NULL) { + streamType = mAudioSink->getAudioStreamType(); + } + if (streamType == AUDIO_STREAM_NOTIFICATION) { + ALOGW("disabling auto-loop for notification"); + mAutoLoop = false; + } + } + if (mLooping || mAutoLoop) { mPlayer->seekToAsync(0); break; } diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index ab8ac79..a31b317 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -879,10 +879,7 @@ void AwesomePlayer::onStreamDone() { } if ((mFlags & LOOPING) - || ((mFlags & AUTO_LOOPING) - && (mAudioSink == NULL || mAudioSink->realtime()))) { - // Don't AUTO_LOOP if we're being recorded, since that cannot be - // turned off and recording would go on indefinitely. + || (mFlags & AUTO_LOOPING)) { seekTo_l(0); |