diff options
-rw-r--r-- | include/media/MediaPlayerInterface.h | 6 | ||||
-rw-r--r-- | include/media/stagefright/AudioPlayer.h | 4 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 90 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.h | 6 | ||||
-rw-r--r-- | media/libstagefright/AudioPlayer.cpp | 18 | ||||
-rw-r--r-- | media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java | 3 |
6 files changed, 105 insertions, 22 deletions
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index a5a1bb8..be06e33 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -62,7 +62,8 @@ public: // AudioSink: abstraction layer for audio output class AudioSink : public RefBase { public: - typedef void (*AudioCallback)( + // Callback returns the number of bytes actually written to the buffer. + typedef size_t (*AudioCallback)( AudioSink *audioSink, void *buffer, size_t size, void *cookie); virtual ~AudioSink() {} @@ -77,8 +78,7 @@ public: virtual status_t getPosition(uint32_t *position) = 0; // If no callback is specified, use the "write" API below to submit - // audio data. Otherwise return a full buffer of audio data on each - // callback. + // audio data. virtual status_t open( uint32_t sampleRate, int channelCount, int format=AudioSystem::PCM_16_BIT, diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h index 843e051..8e5f05f 100644 --- a/include/media/stagefright/AudioPlayer.h +++ b/include/media/stagefright/AudioPlayer.h @@ -90,11 +90,11 @@ private: static void AudioCallback(int event, void *user, void *info); void AudioCallback(int event, void *info); - static void AudioSinkCallback( + static size_t AudioSinkCallback( MediaPlayerBase::AudioSink *audioSink, void *data, size_t size, void *me); - void fillBuffer(void *data, size_t size); + size_t fillBuffer(void *data, size_t size); int64_t getRealTimeUsLocked() const; diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 8e61011..55b06f4 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -1597,9 +1597,12 @@ void MediaPlayerService::AudioOutput::CallbackWrapper( AudioOutput *me = (AudioOutput *)cookie; AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; - (*me->mCallback)( + size_t actualSize = (*me->mCallback)( me, buffer->raw, buffer->size, me->mCallbackCookie); - me->snoopWrite(buffer->raw, buffer->size); + + if (actualSize > 0) { + me->snoopWrite(buffer->raw, actualSize); + } } #undef LOG_TAG @@ -1629,14 +1632,75 @@ status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) return NO_ERROR; } +//////////////////////////////////////////////////////////////////////////////// + +struct CallbackThread : public Thread { + CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink, + MediaPlayerBase::AudioSink::AudioCallback cb, + void *cookie); + +protected: + virtual ~CallbackThread(); + + virtual bool threadLoop(); + +private: + wp<MediaPlayerBase::AudioSink> mSink; + MediaPlayerBase::AudioSink::AudioCallback mCallback; + void *mCookie; + void *mBuffer; + size_t mBufferSize; + + CallbackThread(const CallbackThread &); + CallbackThread &operator=(const CallbackThread &); +}; + +CallbackThread::CallbackThread( + const wp<MediaPlayerBase::AudioSink> &sink, + MediaPlayerBase::AudioSink::AudioCallback cb, + void *cookie) + : mSink(sink), + mCallback(cb), + mCookie(cookie), + mBuffer(NULL), + mBufferSize(0) { +} + +CallbackThread::~CallbackThread() { + if (mBuffer) { + free(mBuffer); + mBuffer = NULL; + } +} + +bool CallbackThread::threadLoop() { + sp<MediaPlayerBase::AudioSink> sink = mSink.promote(); + if (sink == NULL) { + return false; + } + + if (mBuffer == NULL) { + mBufferSize = sink->bufferSize(); + mBuffer = malloc(mBufferSize); + } + + size_t actualSize = + (*mCallback)(sink.get(), mBuffer, mBufferSize, mCookie); + + if (actualSize > 0) { + sink->write(mBuffer, actualSize); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// + status_t MediaPlayerService::AudioCache::open( uint32_t sampleRate, int channelCount, int format, int bufferCount, AudioCallback cb, void *cookie) { LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount); - if (cb != NULL) { - return UNKNOWN_ERROR; // TODO: implement this. - } if (mHeap->getHeapID() < 0) { return NO_INIT; } @@ -1645,9 +1709,25 @@ status_t MediaPlayerService::AudioCache::open( mChannelCount = (uint16_t)channelCount; mFormat = (uint16_t)format; mMsecsPerFrame = 1.e3 / (float) sampleRate; + + if (cb != NULL) { + mCallbackThread = new CallbackThread(this, cb, cookie); + } return NO_ERROR; } +void MediaPlayerService::AudioCache::start() { + if (mCallbackThread != NULL) { + mCallbackThread->run("AudioCache callback"); + } +} + +void MediaPlayerService::AudioCache::stop() { + if (mCallbackThread != NULL) { + mCallbackThread->requestExitAndWait(); + } +} + ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size) { LOGV("write(%p, %u)", buffer, size); diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index ffe1ba0..5c03e47 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -139,9 +139,9 @@ class MediaPlayerService : public BnMediaPlayerService int bufferCount = 1, AudioCallback cb = NULL, void *cookie = NULL); - virtual void start() {} + virtual void start(); virtual ssize_t write(const void* buffer, size_t size); - virtual void stop() {} + virtual void stop(); virtual void flush() {} virtual void pause() {} virtual void close() {} @@ -171,6 +171,8 @@ class MediaPlayerService : public BnMediaPlayerService uint32_t mSize; int mError; bool mCommandComplete; + + sp<Thread> mCallbackThread; }; public: diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp index 4926920..12d7ee2 100644 --- a/media/libstagefright/AudioPlayer.cpp +++ b/media/libstagefright/AudioPlayer.cpp @@ -187,12 +187,12 @@ bool AudioPlayer::reachedEOS() { } // static -void AudioPlayer::AudioSinkCallback( +size_t AudioPlayer::AudioSinkCallback( MediaPlayerBase::AudioSink *audioSink, void *buffer, size_t size, void *cookie) { AudioPlayer *me = (AudioPlayer *)cookie; - me->fillBuffer(buffer, size); + return me->fillBuffer(buffer, size); } void AudioPlayer::AudioCallback(int event, void *info) { @@ -201,17 +201,18 @@ void AudioPlayer::AudioCallback(int event, void *info) { } AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; - fillBuffer(buffer->raw, buffer->size); + size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size); + + buffer->size = numBytesWritten; } -void AudioPlayer::fillBuffer(void *data, size_t size) { +size_t AudioPlayer::fillBuffer(void *data, size_t size) { if (mNumFramesPlayed == 0) { LOGV("AudioCallback"); } if (mReachedEOS) { - memset(data, 0, size); - return; + return 0; } size_t size_done = 0; @@ -244,7 +245,6 @@ void AudioPlayer::fillBuffer(void *data, size_t size) { if (err != OK) { mReachedEOS = true; - memset((char *)data + size_done, 0, size_remaining); break; } @@ -285,7 +285,9 @@ void AudioPlayer::fillBuffer(void *data, size_t size) { } Mutex::Autolock autoLock(mLock); - mNumFramesPlayed += size / mFrameSize; + mNumFramesPlayed += size_done / mFrameSize; + + return size_done; } int64_t AudioPlayer::getRealTimeUs() { diff --git a/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java b/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java index 6b3093f..1434d3f 100644 --- a/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java +++ b/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java @@ -43,10 +43,9 @@ public class SoundPoolTest extends Activity private TestThread mThread; private static final int[] mTestFiles = new int[] { - // FIXME: Restore when Stagefright bug is fixed R.raw.organ441, R.raw.sine441, - //R.raw.test1, + R.raw.test1, R.raw.test2, R.raw.test3, R.raw.test4, |