Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ed937eb authored by Andreas Huber's avatar Andreas Huber
Browse files

Implementation of stagefright-enabled MediaPlayerService::decode functionality

related-to-bug: 2359268
parent 5b5f8652
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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,
+2 −2
Original line number Diff line number Diff line
@@ -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;

+85 −5
Original line number Diff line number Diff line
@@ -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);
+4 −2
Original line number Diff line number Diff line
@@ -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:
+10 −8
Original line number Diff line number Diff line
@@ -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() {
Loading