awesomeplayer_event 分析
来源:互联网 发布:博奥软件官网 编辑:程序博客网 时间:2024/05/26 12:58
awesomeplayer里面,最重要的一个函数,就是AwesomePlayer::onVideoEvent
这个函数囊括了AV同步,元数据读取,帧数据显示等很多工作。
我们前面提到过这个函数。现在针对这个函数总结一下他的工作流程
首先总结一下onVideoEvent是如何产生的
前面讲过,status_t AwesomePlayer::prepareAsync_l() 调用的时候,会调用mQueue.start
首先被创建
//一阵视频解码完,openmax component会触发FILL_BUFFER_DONE的onMessage,
//OMXCodec::on_message中会mBufferFilled.signal, 从而使mVideoSource->read跳出等待,继续往下执行
//以下进行AV同步。具体在前面文章介绍过
并且通过控制触发自己下一次执行的时间,实现了AV同步。
并且通过mVideoSource->read实现了元数据读取,emptythisbuffer命令下发
通过mVideoRenderer->render实现了图像显示,
通过mVideoBuffer->release实现了fillthisbuffer命令下发
这个函数囊括了AV同步,元数据读取,帧数据显示等很多工作。
我们前面提到过这个函数。现在针对这个函数总结一下他的工作流程
首先总结一下onVideoEvent是如何产生的
前面讲过,status_t AwesomePlayer::prepareAsync_l() 调用的时候,会调用mQueue.start
status_t AwesomePlayer::prepareAsync_l() { if (!mQueueStarted) { mQueue.start(); mQueueStarted = true; }}这里实际上就是创建一个线程
<pre name="code" class="cpp">void TimedEventQueue::start() { pthread_create(&mThread, &attr, ThreadWrapper, this);}void *TimedEventQueue::ThreadWrapper(void *me) { static_cast<TimedEventQueue *>(me)->threadEntry();}void TimedEventQueue::threadEntry() { for (;;) { { event_id eventID = 0; for (;;) { 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; if (delay_us > kMaxTimeoutUs) { 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; } } event = removeEventFromQueue_l(eventID);//等待时间到,取事件, } if (event != NULL) { event->fire(this, now_us); //执行事件的对应函数 } }} virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { (mPlayer->*mMethod)(); }
//AwesomePlayer的构造函数里面,执行mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);//在AwesomeEvent的构造函数里,将onVideoEvent函数挂接到mMethod指针上。
AwesomeEvent(AwesomePlayer *player, void (AwesomePlayer::*method)()) : mPlayer(player), mMethod(method) { }
mPlayer和mMethod 都是AwesomeEvent 的成员变量,(*mMethod)() 表示调用该指针指向的函数, mPlayer-> 表示把mPlayer 指针作为(*mMethod)()的第一个参数:this。TimedEventQueue 是一个按照事件约定时间来执行事件携带动作的类。事件的约定时间存在 QueueItem::realtime_us 里,往TimedEventQueue发事件使用 TimedEventQueue::postTimedEvent ,该方法除this以外的第一个参数是事件,第二个参数是该事件约定的执行时间,它是按顺序往列表里填事件的,请看这段代码:
TimedEventQueue::event_id TimedEventQueue::postTimedEvent() {.... List<QueueItem>::iterator it = mQueue.begin(); while (it != mQueue.end() && realtime_us >= (*it).realtime_us) { ++it; } QueueItem item; item.event = event; item.realtime_us = realtime_us;//事件延时触发时间 if (it == mQueue.begin()) { mQueueHeadChangedCondition.signal(); } mQueue.insert(it, item); //这样就把事件填到了列表里面.... }具体到AwesomePlayer::mVideoEvent这个事件,我们做如下说明:
首先被创建
AwesomePlayer::AwesomePlayer(){ mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);}//mVideoEvent 事件创建之后的 mPlayer是AwesomePlayer*, 动作是AwesomePlayer::onVideoEvent。首先在AwesomePlayer::play_l里面,会通过调用postVideoEvent_l来触发第一次onVideoEventvoid AwesomePlayer::postVideoEvent_l(int64_t delayUs) { mVideoEventPending = true; mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);//默认延时10ms}然后onVideoEvent开始进入第一次执行
void AwesomePlayer::onVideoEvent() { for (;;) { status_t err = mVideoSource->read(&mVideoBuffer, &options); // mVideoSource is a video decoder options.clearSeekTo(); break; }//前面我们介绍过,awesomeplayer把一帧数据送给decoder后,会在mVideoSource->read(即OMXCodec::read)等待,
//一阵视频解码完,openmax component会触发FILL_BUFFER_DONE的onMessage,
//OMXCodec::on_message中会mBufferFilled.signal, 从而使mVideoSource->read跳出等待,继续往下执行
//以下进行AV同步。具体在前面文章介绍过
<pre name="code" class="cpp"> if (wasSeeking == NO_SEEK) { //忽略这一帧的显示 // Let's display the first frame after seeking right away. int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; int64_t latenessUs = nowUs - timeUs; if (latenessUs > 500000ll ) { mVideoBuffer->release(); // delete this mediabuffer mVideoBuffer = NULL; mSeeking = SEEK_VIDEO_ONLY; mSeekTimeUs = mediaTimeUs; ///给自己发一个10ms之后执行的事件。触发下一次执行,然后退出 postVideoEvent_l(); return; } if (latenessUs > 40000) { //忽略这一帧的显示 // We're more than 40ms late. mVideoBuffer->release(); // delete this mediabuffer mVideoBuffer = NULL; ++mStats.mNumVideoFramesDropped; ///给自己发一个10ms之后执行的事件。触发下一次执行,然后退出 postVideoEvent_l(); return; } if (latenessUs < -10000) { // We're more than 10ms early. ///给自己发一个10ms之后执行的事件。触发下一次执行,然后退出 postVideoEvent_l(10000); // to display after a while return; } }//以上进行AV同步。具体在前面文章介绍过 mVideoRenderer->render(mVideoBuffer); //// 通过surfaceflinger把数据显示出来 mVideoBuffer->release(); //显示完毕,通过调用signalBufferReturned,掉用fillOutputBuffer mVideoBuffer = NULL; ///给自己发一个10ms之后执行的事件。触发下一次执行,然后退出 postVideoEvent_l();}实际上onVideoEvent是通过一次次的触发自己下一次执行,来实现的一帧帧的解码。
并且通过控制触发自己下一次执行的时间,实现了AV同步。
并且通过mVideoSource->read实现了元数据读取,emptythisbuffer命令下发
通过mVideoRenderer->render实现了图像显示,
通过mVideoBuffer->release实现了fillthisbuffer命令下发
0 0
- awesomeplayer_event 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 大家帮忙分析分析!
- FFMpeg分析详细分析
- FFMpeg分析详细分析
- core 分析的分析
- 写给自己,分析分析
- FFMpeg分析详细分析
- 图像分析------直方图分析
- 静态分析 - 数据流分析
- C++学习笔记之三五法则
- Alex’s Game(I)
- Java 入门 之 面向对象 封装、继承与多态(二)
- C#程序开发中经常遇到的10条实用的代码
- Codeforces Round 331 (Div 2)BWilbur and Array(贪心)
- awesomeplayer_event 分析
- Java内存管理再探究
- Fragment与activity生命周期详细图解
- Day5_易语言/中文编程
- storyBoard
- w3c JavaScript 基础
- Maven安装配置
- 在拓胜培训Java,每天的点点滴滴。
- js中的getDate() getMonth() getFullYear()方法