码迷,mamicode.com
首页 > 其他好文 > 详细

TimedEventQueue分析

时间:2014-08-21 17:16:24      阅读:297      评论:0      收藏:0      [点我收藏+]

标签:android   awesomeplayer   timedeventqueue   时间事件队列   media   

AwesomePlayer里面定义了一个TimedEventQueue,通过向它发事件消息,来驱动player的运转。

定义在AwesomePlayer.h里面,如下:

TimedEventQueue mQueue;

TimedEventQueue中维护了一个队列,外面通过调用其提供的方法postEvent, postEventWithDelay等等来向队列添加事件,在执行完mQueue.start()后,TimedEventQueue将启动一个线程,用来取出队列中的事件,并执行之。

先看mQueue.start()

void TimedEventQueue::start() {
    if (mRunning) {
        return;
    }

    mStopped = false;

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    // 创建线程,线程函数为ThreadWrapper
    pthread_create(&mThread, &attr, ThreadWrapper, this);

    pthread_attr_destroy(&attr);

    mRunning = true;
}

// static
void *TimedEventQueue::ThreadWrapper(void *me) {

    androidSetThreadPriority(0, ANDROID_PRIORITY_FOREGROUND);

	// 线程函数又调用了自己的threadEntry()
    static_cast<TimedEventQueue *>(me)->threadEntry();

    return NULL;
}

void TimedEventQueue::threadEntry() {
    prctl(PR_SET_NAME, (unsigned long)"TimedEventQueue", 0, 0, 0);

    for (;;) {
        int64_t now_us = 0;
        sp<Event> event;

        {
            Mutex::Autolock autoLock(mLock);

            if (mStopped) {
                break;
            }

            // 等待队列中有事件来
            while (mQueue.empty()) {
                mQueueNotEmptyCondition.wait(mLock);
            }

            event_id eventID = 0;
            for (;;) {
                if (mQueue.empty()) {
                    // The only event in the queue could have been cancelled
                    // while we were waiting for its scheduled time.
                    break;
                }

                // 往队列中添加事件是按照事件的时间先后顺序添加的
                // 所以这里是取执行时间最靠前的事件
                List<QueueItem>::iterator it = mQueue.begin();
                eventID = (*it).event->eventID();

                now_us = ALooper::GetNowUs();
                int64_t when_us = (*it).realtime_us;

                int64_t delay_us;
                if (when_us < 0 || when_us == INT64_MAX) {
                    delay_us = 0;
                } else {
                    delay_us = when_us - now_us;
                }

                if (delay_us <= 0) {
                    break; // 不需要等待
                }

                static int64_t kMaxTimeoutUs = 10000000ll;  // 10 secs
                bool timeoutCapped = false;
                // 等待时间超过10secs,则分成几次来等
                if (delay_us > kMaxTimeoutUs) {
                    ALOGW("delay_us exceeds max timeout: %lld us", delay_us);

                    // We'll never block for more than 10 secs, instead
                    // we will split up the full timeout into chunks of
                    // 10 secs at a time. This will also avoid overflow
                    // when converting from us to ns.
                    delay_us = kMaxTimeoutUs;
                    timeoutCapped = true;
                }

                // 等待相应的时长
                status_t err = mQueueHeadChangedCondition.waitRelative(
                        mLock, delay_us * 1000ll);

                if (!timeoutCapped && err == -ETIMEDOUT) {
                    // We finally hit the time this event is supposed to
                    // trigger.
                    now_us = ALooper::GetNowUs();
                    break;
                }
            }

            // The event w/ this id may have been cancelled while we're
            // waiting for its trigger-time, in that case
            // removeEventFromQueue_l will return NULL.
            // Otherwise, the QueueItem will be removed
            // from the queue and the referenced event returned.
            event = removeEventFromQueue_l(eventID);
        }

        // 执行取出的事件
        if (event != NULL) {
            // Fire event with the lock NOT held.
            event->fire(this, now_us);
        }
    }
}

可见,mQueue.start()之后,TimedEventQueue就启动了一个线程,等待外面给它发event,然后取出消息,并通过调用event->fire(this, now_us)执行之。

接下来,就去看看AwesomePlayer往队列里发的event。

mAsyncPrepareEvent = new AwesomeEvent(

           this, &AwesomePlayer::onPrepareAsyncEvent);

mQueue.postEvent(mAsyncPrepareEvent);

AwesomeEvent的定义如下:

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

protected:
    virtual ~AwesomeEvent() {}

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

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

    AwesomeEvent(const AwesomeEvent &);
    AwesomeEvent &operator=(const AwesomeEvent &);
};

在构造函数中,mPlayer被赋值为this,即AwesomePlayer自己,mMethod被赋值为AwesomePlayer::onPrepareAsyncEvent。AwesomeEvent实现了fire方法,(mPlayer->*mMethod)(),综合前面对TimedEventQueue的了解,当这个AwesomeEvent被post到TimedEventQueue的队列后,就会在TimedEventQueue启动的线程函数中被取出,然后会调用event的fire函数,在这里就是调用AwesomePlayer的onPrepareAsyncEvent方法了。

AwesomePlayer里面定义的AwesomeEvent有:

mVideoEvent = new AwesomeEvent(this,&AwesomePlayer::onVideoEvent);

mStreamDoneEvent = new AwesomeEvent(this,&AwesomePlayer::onStreamDone);

mBufferingEvent = new AwesomeEvent(this,&AwesomePlayer::onBufferingUpdate);

mVideoLagEvent = new AwesomeEvent(this,&AwesomePlayer::onVideoLagUpdate);

mAsyncPrepareEvent = new AwesomeEvent(

           this, &AwesomePlayer::onPrepareAsyncEvent);

等等……

到此,TimedEventQueue分析完毕。

TimedEventQueue分析,布布扣,bubuko.com

TimedEventQueue分析

标签:android   awesomeplayer   timedeventqueue   时间事件队列   media   

原文地址:http://blog.csdn.net/super_dc/article/details/38731163

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!