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

Commit ba530682 authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Properly implement asynchronous preparation of media playback."

parents 1655f9a8 6be780eb
Loading
Loading
Loading
Loading
+2 −21
Original line number Diff line number Diff line
@@ -49,30 +49,11 @@ status_t StagefrightPlayer::setVideoSurface(const sp<ISurface> &surface) {
}

status_t StagefrightPlayer::prepare() {
    LOGV("prepare");

    int32_t width, height;
    if (mPlayer->getVideoDimensions(&width, &height) != OK) {
        width = height = 0;
    }

    sendEvent(MEDIA_SET_VIDEO_SIZE, width, height);

    return OK;
    return mPlayer->prepare();
}

status_t StagefrightPlayer::prepareAsync() {
    LOGV("prepareAsync");

    status_t err = prepare();

    if (err != OK) {
        return err;
    }

    sendEvent(MEDIA_PREPARED);

    return OK;
    return mPlayer->prepareAsync();
}

status_t StagefrightPlayer::start() {
+76 −22
Original line number Diff line number Diff line
@@ -37,21 +37,23 @@
namespace android {

struct AwesomeEvent : public TimedEventQueue::Event {
    AwesomeEvent(AwesomePlayer *player, int32_t code)
    AwesomeEvent(
            AwesomePlayer *player,
            void (AwesomePlayer::*method)())
        : mPlayer(player),
          mCode(code) {
          mMethod(method) {
    }

protected:
    virtual ~AwesomeEvent() {}

    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
        mPlayer->onEvent(mCode);
        (mPlayer->*mMethod)();
    }

private:
    AwesomePlayer *mPlayer;
    int32_t mCode;
    void (AwesomePlayer::*mMethod)();

    AwesomeEvent(const AwesomeEvent &);
    AwesomeEvent &operator=(const AwesomeEvent &);
@@ -115,13 +117,16 @@ AwesomePlayer::AwesomePlayer()

    DataSource::RegisterDefaultSniffers();

    mVideoEvent = new AwesomeEvent(this, 0);
    mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
    mVideoEventPending = false;
    mStreamDoneEvent = new AwesomeEvent(this, 1);
    mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
    mStreamDoneEventPending = false;
    mBufferingEvent = new AwesomeEvent(this, 2);
    mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
    mBufferingEventPending = false;
    mCheckAudioStatusEvent = new AwesomeEvent(this, 3);

    mCheckAudioStatusEvent = new AwesomeEvent(
            this, &AwesomePlayer::onCheckAudioStatus);

    mAudioStatusEventPending = false;

    mQueue.start();
@@ -287,12 +292,12 @@ void AwesomePlayer::reset_l() {
    mPrefetcher.clear();
}

void AwesomePlayer::notifyListener_l(int msg, int ext1) {
void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
    if (mListener != NULL) {
        sp<MediaPlayerBase> listener = mListener.promote();

        if (listener != NULL) {
            listener->sendEvent(msg, ext1);
            listener->sendEvent(msg, ext1, ext2);
        }
    }
}
@@ -623,18 +628,7 @@ status_t AwesomePlayer::setVideoSource(sp<MediaSource> source) {
    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
}

void AwesomePlayer::onEvent(int32_t code) {
    if (code == 1) {
        onStreamDone();
        return;
    } else if (code == 2) {
        onBufferingUpdate();
        return;
    } else if (code == 3) {
        onCheckAudioStatus();
        return;
    }

void AwesomePlayer::onVideoEvent() {
    Mutex::Autolock autoLock(mLock);

    mVideoEventPending = false;
@@ -819,5 +813,65 @@ void AwesomePlayer::onCheckAudioStatus() {
    postCheckAudioStatusEvent_l();
}

status_t AwesomePlayer::prepare() {
    Mutex::Autolock autoLock(mLock);

    status_t err = prepareAsync_l();

    if (err != OK) {
        return err;
    }

    while (mAsyncPrepareEvent != NULL) {
        mPreparedCondition.wait(mLock);
    }

    return OK;
}

status_t AwesomePlayer::prepareAsync() {
    Mutex::Autolock autoLock(mLock);
    return prepareAsync_l();
}

status_t AwesomePlayer::prepareAsync_l() {
    if (mAsyncPrepareEvent != NULL) {
        return UNKNOWN_ERROR;  // async prepare already pending.
    }

    mAsyncPrepareEvent = new AwesomeEvent(
            this, &AwesomePlayer::onPrepareAsyncEvent);

    mQueue.postEvent(mAsyncPrepareEvent);

    return OK;
}

void AwesomePlayer::onPrepareAsyncEvent() {
    sp<Prefetcher> prefetcher;

    {
        Mutex::Autolock autoLock(mLock);
        prefetcher = mPrefetcher;
    }

    if (prefetcher != NULL) {
        prefetcher->prepare();
    }

    Mutex::Autolock autoLock(mLock);

    if (mVideoWidth < 0 || mVideoHeight < 0) {
        notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
    } else {
        notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
    }

    notifyListener_l(MEDIA_PREPARED);

    mAsyncPrepareEvent = NULL;
    mPreparedCondition.signal();
}

}  // namespace android
+17 −10
Original line number Diff line number Diff line
@@ -171,7 +171,7 @@ void Prefetcher::threadFunc() {
    }
}

int64_t Prefetcher::getCachedDurationUs() {
int64_t Prefetcher::getCachedDurationUs(bool *noMoreData) {
    Mutex::Autolock autoLock(mLock);

    int64_t minCacheDurationUs = -1;
@@ -197,9 +197,25 @@ int64_t Prefetcher::getCachedDurationUs() {
        }
    }

    if (noMoreData) {
        *noMoreData = minCacheDurationUs < 0;
    }

    return minCacheDurationUs < 0 ? 0 : minCacheDurationUs;
}

status_t Prefetcher::prepare() {
    // Buffer about 2 secs worth of data on prepare.

    int64_t duration;
    bool noMoreData;
    do {
        duration = getCachedDurationUs(&noMoreData);
    } while (!noMoreData && duration < 2000000);

    return OK;
}

////////////////////////////////////////////////////////////////////////////////

PrefetchedSource::PrefetchedSource(
@@ -232,15 +248,6 @@ status_t PrefetchedSource::start(MetaData *params) {

    mStarted = true;

    for (;;) {
        // Buffer 2 secs on startup.
        if (mReachedEOS || mCacheDurationUs > 2000000) {
            break;
        }

        mCondition.wait(mLock);
    }

    return OK;
}

+10 −2
Original line number Diff line number Diff line
@@ -57,6 +57,10 @@ struct AwesomePlayer {

    void reset();

    status_t prepare();
    status_t prepareAsync();
    status_t prepareAsync_l();

    status_t play();
    status_t pause();

@@ -121,6 +125,9 @@ private:
    sp<TimedEventQueue::Event> mCheckAudioStatusEvent;
    bool mAudioStatusEventPending;

    sp<TimedEventQueue::Event> mAsyncPrepareEvent;
    Condition mPreparedCondition;

    void postVideoEvent_l(int64_t delayUs = -1);
    void postBufferingEvent_l();
    void postStreamDoneEvent_l();
@@ -143,13 +150,14 @@ private:
    status_t setAudioSource(sp<MediaSource> source);
    status_t setVideoSource(sp<MediaSource> source);

    void onEvent(int32_t code);
    void onStreamDone();

    void notifyListener_l(int msg, int ext1 = 0);
    void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0);

    void onVideoEvent();
    void onBufferingUpdate();
    void onCheckAudioStatus();
    void onPrepareAsyncEvent();

    AwesomePlayer(const AwesomePlayer &);
    AwesomePlayer &operator=(const AwesomePlayer &);
+3 −1
Original line number Diff line number Diff line
@@ -34,7 +34,9 @@ struct Prefetcher : public RefBase {
    // that will benefit from prefetching/caching the original one.
    sp<MediaSource> addSource(const sp<MediaSource> &source);

    int64_t getCachedDurationUs();
    int64_t getCachedDurationUs(bool *noMoreData = NULL);

    status_t prepare();

protected:
    virtual ~Prefetcher();