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

Commit 014df71e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "MediaClock: add timer"

parents 669446c8 7b6f67d1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -78,6 +78,8 @@ NuPlayerDriver::NuPlayerDriver(pid_t pid)
    ALOGD("NuPlayerDriver(%p) created, clientPid(%d)", this, pid);
    mLooper->setName("NuPlayerDriver Looper");

    mMediaClock->init();

    // set up an analytics record
    mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
    mAnalyticsItem->generateSessionID();
+101 −2
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@
#include <media/stagefright/MediaClock.h>

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>

namespace android {

@@ -34,10 +34,41 @@ MediaClock::MediaClock()
      mAnchorTimeRealUs(-1),
      mMaxTimeMediaUs(INT64_MAX),
      mStartingTimeMediaUs(-1),
      mPlaybackRate(1.0) {
      mPlaybackRate(1.0),
      mGeneration(0) {
    mLooper = new ALooper;
    mLooper->setName("MediaClock");
    mLooper->start(false /* runOnCallingThread */,
                   false /* canCallJava */,
                   ANDROID_PRIORITY_AUDIO);
}

void MediaClock::init() {
    mLooper->registerHandler(this);
}

MediaClock::~MediaClock() {
    reset();
    if (mLooper != NULL) {
        mLooper->unregisterHandler(id());
        mLooper->stop();
    }
}

void MediaClock::reset() {
    Mutex::Autolock autoLock(mLock);
    auto it = mTimers.begin();
    while (it != mTimers.end()) {
        it->second->setInt32("reason", TIMER_REASON_RESET);
        it->second->post();
        it = mTimers.erase(it);
    }
    mAnchorTimeMediaUs = -1;
    mAnchorTimeRealUs = -1;
    mMaxTimeMediaUs = INT64_MAX;
    mStartingTimeMediaUs = -1;
    mPlaybackRate = 1.0;
    ++mGeneration;
}

void MediaClock::setStartingTimeMedia(int64_t startingTimeMediaUs) {
@@ -82,6 +113,9 @@ void MediaClock::updateAnchor(
    }
    mAnchorTimeRealUs = nowUs;
    mAnchorTimeMediaUs = nowMediaUs;

    ++mGeneration;
    processTimers_l();
}

void MediaClock::updateMaxTimeMedia(int64_t maxTimeMediaUs) {
@@ -105,6 +139,11 @@ void MediaClock::setPlaybackRate(float rate) {
    }
    mAnchorTimeRealUs = nowUs;
    mPlaybackRate = rate;

    if (rate > 0.0) {
        ++mGeneration;
        processTimers_l();
    }
}

float MediaClock::getPlaybackRate() const {
@@ -165,4 +204,64 @@ status_t MediaClock::getRealTimeFor(
    return OK;
}

void MediaClock::addTimer(const sp<AMessage> &notify, int64_t mediaTimeUs) {
    Mutex::Autolock autoLock(mLock);
    int64_t nextMediaTimeUs = INT64_MAX;
    if (!mTimers.empty()) {
        nextMediaTimeUs = mTimers.begin()->first;
    }

    mTimers.emplace(mediaTimeUs, notify);
    if (mediaTimeUs < nextMediaTimeUs) {
        ++mGeneration;
        processTimers_l();
    }
}

void MediaClock::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatTimeIsUp:
        {
            int32_t generation;
            CHECK(msg->findInt32("generation", &generation));

            Mutex::Autolock autoLock(mLock);
            if (generation != mGeneration) {
                break;
            }
            processTimers_l();
            break;
        }

        default:
            TRESPASS();
            break;
    }
}

void MediaClock::processTimers_l() {
    int64_t nowMediaTimeUs;
    status_t status = getMediaTime_l(
            ALooper::GetNowUs(), &nowMediaTimeUs, false /* allowPastMaxTime */);

    if (status != OK) {
        return;
    }

    auto it = mTimers.begin();
    while (it != mTimers.end() && it->first <= nowMediaTimeUs) {
        it->second->setInt32("reason", TIMER_REASON_REACHED);
        it->second->post();
        it = mTimers.erase(it);
    }

    if (it == mTimers.end() || mPlaybackRate == 0.0 || mAnchorTimeMediaUs < 0) {
        return;
    }

    sp<AMessage> msg = new AMessage(kWhatTimeIsUp, this);
    msg->setInt32("generation", mGeneration);
    msg->post((it->first - nowMediaTimeUs) / (double)mPlaybackRate);
}

}  // namespace android
+1 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ MediaSync::MediaSync()
        mNextBufferItemMediaUs(-1),
        mPlaybackRate(0.0) {
    mMediaClock = new MediaClock;
    mMediaClock->init();

    // initialize settings
    mPlaybackSettings = AUDIO_PLAYBACK_RATE_DEFAULT;
+26 −2
Original line number Diff line number Diff line
@@ -18,7 +18,8 @@

#define MEDIA_CLOCK_H_

#include <media/stagefright/foundation/ABase.h>
#include <map>
#include <media/stagefright/foundation/AHandler.h>
#include <utils/Mutex.h>
#include <utils/RefBase.h>

@@ -26,8 +27,15 @@ namespace android {

struct AMessage;

struct MediaClock : public RefBase {
struct MediaClock : public AHandler {
    enum {
        TIMER_REASON_REACHED = 0,
        TIMER_REASON_NO_CLOCK = 1,
        TIMER_REASON_RESET = 2,
    };

    MediaClock();
    void init();

    void setStartingTimeMedia(int64_t startingTimeMediaUs);

@@ -54,15 +62,28 @@ struct MediaClock : public RefBase {
    // The result is saved in |outRealUs|.
    status_t getRealTimeFor(int64_t targetMediaUs, int64_t *outRealUs) const;

    void addTimer(const sp<AMessage> &notify, int64_t mediaTimeUs);

    void reset();

protected:
    virtual ~MediaClock();

    virtual void onMessageReceived(const sp<AMessage> &msg);

private:
    enum {
        kWhatTimeIsUp = 'tIsU',
    };

    status_t getMediaTime_l(
            int64_t realUs,
            int64_t *outMediaUs,
            bool allowPastMaxTime) const;

    void processTimers_l();

    sp<ALooper> mLooper;
    mutable Mutex mLock;

    int64_t mAnchorTimeMediaUs;
@@ -72,6 +93,9 @@ private:

    float mPlaybackRate;

    int32_t mGeneration;
    std::multimap<int64_t, sp<AMessage> > mTimers;

    DISALLOW_EVIL_CONSTRUCTORS(MediaClock);
};