Android多媒体开发【7】-- AwesomePlayer中TimedEventQueue-event事件调度器

本文深入解析了AwesomePlayer播放器中利用TimedEventQueue实现事件调度的技术细节,包括其内部结构、工作原理以及如何将音视频处理功能与事件绑定,通过事件队列有序执行耗时操作,提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Android多媒体开发【7】-- AwesomePlayer中TimedEventQueue-event事件调度器

分类: 【多媒体技术】 【Android】   2323人阅读  评论(2)  收藏  举报

上文已经大概介绍了播放器的几大主要部分,但是有了这些功能组件也不能叫做播放器。需要某种方式将这些单独的功能组件驱动起来,形成一个整体的功能。

视频处理过程中有很多都是十分耗时的,如果都放在一个大的线程空间中。用户体验的效果可想而知。所以通常都是做异步操作。

AwesomePlayer是通过event事件调度来实现这些功能之间的驱动和调用的。

AwesomePlayer中的内部变量

[cpp]  view plain copy
  1. TimedEventQueue mQueue;  

这个mQueue就是AwesomePlayer的事件队列,也是事件调度器。从他类型的名字上就能很清楚的看出他是以时间为基础事件队列。接下来看看它是怎么玩转的。


1.先来看TimedEventQueue的内部结构,TimedEventQueue内部有一个 List<QueueItem>,每个QueueItem包含enent和时间

[cpp]  view plain copy
  1. struct QueueItem {  
  2.        sp<Event> event;  
  3.        int64_t realtime_us;  
  4.    };  
有一个独立线程 threadEntry是在TimedEventQueue::start被创建,TimedEventQueue::stop被销毁的。

[cpp]  view plain copy
  1. void TimedEventQueue::start() {  
  2.     if (mRunning) {  
  3.         return;  
  4.     }  
  5.   
  6.     mStopped = false;  
  7.   
  8.     pthread_attr_t attr;  
  9.     pthread_attr_init(&attr);  
  10.     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);  
  11.   
  12.     pthread_create(&mThread, &attr, ThreadWrapper, this);  
  13.   
  14.     pthread_attr_destroy(&attr);  
  15.   
  16.     mRunning = true;  
  17. }  
  18.   
  19. void TimedEventQueue::stop(bool flush) {  
  20.     if (!mRunning) {  
  21.         return;  
  22.     }  
  23.   
  24.     if (flush) {  
  25.         postEventToBack(new StopEvent);  
  26.     } else {  
  27.         postTimedEvent(new StopEvent, INT64_MIN);  
  28.     }  
  29.   
  30.     void *dummy;  
  31.     pthread_join(mThread, &dummy);  
  32.   
  33.     mQueue.clear();  
  34.   
  35.     mRunning = false;  
  36. }  

2. List<QueueItem>目的就是按照延时时间维护一个event事件队列, threadEntry线程就是不断的从队列的头取出一个event,然后通过  event->fire(this, now_us); 回调到这个event事件提前注册好的相对应功能函数。

3.然后看看AwesomePlayer是怎么用TimedEventQueue,AwesomePlayer会定义很多类型的event事件,并把和这些事件相关的功能函数一定绑定起来。

[cpp]  view plain copy
  1. mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);  
  2. mVideoEventPending = false;  
  3. mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);  
  4. mStreamDoneEventPending = false;  
  5. mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);  
  6. mBufferingEventPending = false;  
  7. mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);  
  8. mVideoEventPending = false;  
  9. 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]  view plain copy
  1. status_t AwesomePlayer::prepareAsync_l() {  
  2.     if (mFlags & PREPARING) {  
  3.         return UNKNOWN_ERROR;  // async prepare already pending  
  4.     }  
  5.   
  6.     if (!mQueueStarted) {  
  7.         mQueue.start();  
  8.         mQueueStarted = true;  
  9.     }  
  10.   
  11.     modifyFlags(PREPARING, SET);  
  12.     mAsyncPrepareEvent = new AwesomeEvent(  
  13.             this, &AwesomePlayer::onPrepareAsyncEvent);  
  14.   
  15.     mQueue.postEvent(mAsyncPrepareEvent);  
  16.   
  17.     return OK;  
  18. }  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值