当前位置:操作系统 > 安卓/Android >>

Android多媒体开发笔记[7]-- AwesomePlayer 学习之TimedEventQueue-event事件调度器

视频处理过程中有很多都是十分耗时的,如果都放在一个大的线程空间中。用户体验的效果可想而知。所以通常都是做异步操作。
AwesomePlayer是通过event事件调度来实现这些功能之间的驱动和调用的。
AwesomePlayer中的内部变量
[cpp] 
TimedEventQueue mQueue; 
这个mQueue就是AwesomePlayer的事件队列,也是事件调度器。从他类型的名字上就能很清楚的看出他是以时间为基础事件队列。接下来看看它是怎么玩转的。

1.先来看TimedEventQueue的内部结构,TimedEventQueue内部有一个 List<QueueItem>,每个QueueItem包含enent和时间
[cpp] 
struct QueueItem { 
       sp<Event> event; 
       int64_t realtime_us; 
   }; 
有一个独立线程threadEntry是在TimedEventQueue::start被创建,TimedEventQueue::stop被销毁的。
[cpp] 
void TimedEventQueue::start() { 
    if (mRunning) { 
        return; 
    } 
 
    mStopped = false; 
 
    pthread_attr_t attr; 
    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
 
    pthread_create(&mThread, &attr, ThreadWrapper, this); 
 
    pthread_attr_destroy(&attr); 
 
    mRunning = true; 

 
void TimedEventQueue::stop(bool flush) { 
    if (!mRunning) { 
        return; 
    } 
 
    if (flush) { 
        postEventToBack(new StopEvent); 
    } else { 
        postTimedEvent(new StopEvent, INT64_MIN); 
    } 
 
    void *dummy; 
    pthread_join(mThread, &dummy); 
 
    mQueue.clear(); 
 
    mRunning = false; 

2.List<QueueItem>目的就是按照延时时间维护一个event事件队列,threadEntry线程就是不断的从队列的头取出一个event,然后通过  event->fire(this, now_us); 回调到这个event事件提前注册好的相对应功能函数。
3.然后看看AwesomePlayer是怎么用TimedEventQueue,AwesomePlayer会定义很多类型的event事件,并把和这些事件相关的功能函数一定绑定起来。
[cpp] 
mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent); 
mVideoEventPending = false; 
mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone); 
mStreamDoneEventPending = false; 
mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate); 
mBufferingEventPending = false; 
mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate); 
mVideoEventPending = false; 
mCheckAudioStatusEvent = new AwesomeEvent(this, &AwesomePlayer::onCheckAudioStatus); 
  原因之前也说了,因为好多音视频处理的功能是十分耗时间的,假如AwesomePlayer 想用某个功能,他并不是直线去调用它,而是抽象成一种AwesomeEvent,将想要调用的功能函数与事件捆绑。通过TimedEventQueue::postTimedEvent(),按照延时的优先顺序把它放到TimedEventQueue的队列之中。然后AwesomePlayer就不管了。TimedEventQueue start之后,自己内部的线程会从队列中依次取出这些事件,然后通过event->fire回调事件的功能函数。这样就达到了AwesomePlayer的目的。
4.之前也介绍过mediaPlayer大致流程就是
mediaPlayer.setDataSource(path); 
mediaPlayer.prepare(); 
mediaPlayer.start();
在AwesomePlayer 也是这种流程,在AwesomePlayer prepare()相关函数中。
[cpp]
status_t AwesomePlayer::prepareAsync_l() { 
    if (mFlags & PREPARING) { 
        return UNKNOWN_ERROR;  // async prepare already pending 
    } 
 
    if (!mQueueStarted) { 
        mQueue.start(); 
        mQueueStarted = true; 
    } 
 
    modifyFlags(PREPARING, SET); 
    mAsyncPrepareEvent = new AwesomeEvent( 
            this, &AwesomePlayer::onPrepareAsyncEvent); 
 
    mQueue.postEvent(mAsyncPrepareEvent); 
 
    return OK; 

他并没有实际的调用onPrepareAsyncEvent()真正的功能函数,他只是把mQueue start之后,然后创建个mAsyncPrepareEvent事件,把它插入到mQueue之中就不管了,具体调用是由mQueue中的threadEntry线程来做。

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,