Implementation of stagefright-enabled MediaPlayerService::decode functionality

related-to-bug: 2359268
This commit is contained in:
Andreas Huber
2010-02-09 16:59:18 -08:00
parent 5b5f8652da
commit 6ed937ebe9
6 changed files with 105 additions and 22 deletions

View File

@@ -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,

View File

@@ -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;

View File

@@ -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);

View File

@@ -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:

View File

@@ -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() {

View File

@@ -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,