Android_ics openmax in stagefright 学习记录------2
来源:互联网 发布:陌交软件怎么样 编辑:程序博客网 时间:2024/06/05 01:51
///////////////////////////////////////////////4,回到awesomeplayer initVideoDecoder()中///////////////////////////////////////////// mVideoSource = OMXCodec::Create( mClient.interface(), mVideoTrack->getFormat(), false, // createEncoder mVideoTrack, NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL); if (mVideoSource != NULL) { int64_t durationUs; if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { Mutex::Autolock autoLock(mMiscStateLock); if (mDurationUs < 0 || durationUs > mDurationUs) { mDurationUs = durationUs; } } //这里的mVideoSource就是上面返回的OMXCodec类型,所以mVideoSource->start()的函数定义如下,但是这里的OMXCodec类型靠node_id来标示,而且OMXCodec(mVideoSource)所扮演的角色类型也不同(setComponentRole())。 status_t err = mVideoSource->start();status_t OMXCodec::start(MetaData *meta) { CODEC_LOGV("OMXCodec::start "); Mutex::Autolock autoLock(mLock); if(mPaused) { if (!strncmp(mComponentName, "OMX.qcom.", 9)) { while (isIntermediateState(mState)) { mAsyncCompletion.wait(mLock); } CHECK_EQ(mState, (status_t)PAUSED); status_t err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateExecuting); CHECK_EQ(err, (status_t)OK); setState(IDLE_TO_EXECUTING); mPaused = false; while (mState != EXECUTING && mState != ERROR) { mAsyncCompletion.wait(mLock); } drainInputBuffers(); return mState == ERROR ? UNKNOWN_ERROR : OK; } else { // SW Codec mPaused = false; return OK; } } if (mState != LOADED) { return UNKNOWN_ERROR; } sp<MetaData> params = new MetaData; if (mQuirks & kWantsNALFragments) { params->setInt32(kKeyWantsNALFragments, true); } if (meta) { int64_t startTimeUs = 0; int64_t timeUs; if (meta->findInt64(kKeyTime, &timeUs)) { startTimeUs = timeUs; } params->setInt64(kKeyTime, startTimeUs); } //第一次跳过前面的代码,走到这里,注意这里的mSource是OMXCodec构造函数中传进来的。追根溯源会发 现这里的mSource其实是mVideoTrack(awesomeplayer的成员变量),而mVideoTrack又是在AwesomePlayer::setVideoSource中被赋值的,在awesomeplayer的setdatasource()函数中setVideoSource(extractor->getTrack(i));所以这里的mSource应该是一个具体的XXXExtractor.getTrack(i)之后得到的。最终发现,mSource实际上是某种格式的一段媒体流。例如MPEG4Source等等。所以这个start函数的做用是根据这段媒体流的实际需要,分配一个合适大小的buf供以后使用。 status_t err = mSource->start(params.get()); if (err != OK) { return err; } mCodecSpecificDataIndex = 0; mInitialBufferSubmit = true; mSignalledEOS = false; mNoMoreOutputData = false; mOutputPortSettingsHaveChanged = false; mSeekTimeUs = -1; mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC; mTargetTimeUs = -1; mFilledBuffers.clear(); mPaused = false; //从这个函数开始通过OMX和OMX的components通信了 return init();}status_t OMXCodec::init() { // mLock is held. CHECK_EQ((int)mState, (int)LOADED); status_t err; //mQuirks是一些和具体编解码组件相关的特性参数,他描述了该组件在工作时候需要的一些注意事项 //mQuirks主要很硬件编解码组件有关 if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) { //向特定的node放送Command,这个node有node_id即mNode表示,后面会详细介绍------------- 1 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); CHECK_EQ(err, (status_t)OK); setState(LOADED_TO_IDLE); } //为不同的nodeInstance分配其输入和输出端口上的buffer,并确定分配大小和分配策略 err = allocateBuffers(); if (err != (status_t)OK) { CODEC_LOGE("Allocate Buffer failed - error = %d", err); setState(ERROR); return err; } if (mQuirks & kRequiresLoadedToIdleAfterAllocation) { err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); CHECK_EQ(err, (status_t)OK); setState(LOADED_TO_IDLE); } while (mState != EXECUTING && mState != ERROR) { mAsyncCompletion.wait(mLock); } return mState == ERROR ? UNKNOWN_ERROR : OK;}/////////////////////////////////////////////////////////////////////5,看看mOMX->sendCommand(mNode,...,...)做了什么///////////////////////////////////////////////////////////////////在OMXCodec会通过OMX服务去调用://该函数会查找node_id号所对应的nodeInstance,然后去调用这个nodeInstance的sendCommand函数。status_t OMX::sendCommand( node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { return findInstance(node)->sendCommand(cmd, param);}|||V//注意这里这个OMXNodeInstance对应就是具体node了,OMX_SendCommand函数中的第一个参数就是在instance->setHandle(*node, handle)传进出的,而且这个handle是由mMaster->makeComponentInstance传出的,上面有提到。status_t OMXNodeInstance::sendCommand( OMX_COMMANDTYPE cmd, OMX_S32 param) { Mutex::Autolock autoLock(mLock); OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); return StatusFromOMXError(err);}//OMX_SendCommand由下面的宏定义,可以看到最后调用的就是那个mHandle的SendCommand方法#define OMX_SendCommand( \ hComponent, \ Cmd, \ nParam, \ pCmdData) \ ((OMX_COMPONENTTYPE*)hComponent)->SendCommand( \ hComponent, \ Cmd, \ nParam, \ pCmdData) /* Macro End *///特别要注意的地方是上面((OMX_COMPONENTTYPE*)hComponent)->SendCommand函数实际上是调用的过程是,首先通过SoftOMXComponent::SendCommandWrapper----->SoftOMXComponent *me =(SoftOMXComponent *)((OMX_COMPONENTTYPE *)component)->pComponentPrivate;(me被转换成一个this指针)---->me->sendCommand(cmd, param, data);(这个me->sendCommand调用的肯定是SimpleSoftOMXComponent::sendCommand) 注意一个继承关系 SoftMPEG4--->SimpleSoftOMXComponent--->SoftOMXComponent (箭头理解为继承于)//sendCommand的函数实现如下:OMX_ERRORTYPE SimpleSoftOMXComponent::sendCommand( OMX_COMMANDTYPE cmd, OMX_U32 param, OMX_PTR data) { CHECK(data == NULL); sp<AMessage> msg = new AMessage(kWhatSendCommand, mHandler->id()); msg->setInt32("cmd", cmd); msg->setInt32("param", param); //消息被投递出去了 msg->post();------------------------------------------------------- 1 return OMX_ErrorNone;}//消息投递出去之后,什么时候得到处理呢?看下 SimpleSoftOMXComponent的构造函数就明白了SimpleSoftOMXComponent::SimpleSoftOMXComponent( const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, OMX_COMPONENTTYPE **component) : SoftOMXComponent(name, callbacks, appData, component), mLooper(new ALooper), mHandler(new AHandlerReflector<SimpleSoftOMXComponent>(this)), mState(OMX_StateLoaded), mTargetState(OMX_StateLoaded) { mLooper->setName(name); mLooper->registerHandler(mHandler); mLooper->start( false, // runOnCallingThread false, // canCallJava ANDROID_PRIORITY_FOREGROUND);}//在 SimpleSoftOMXComponent中有一个mHandler(new AHandlerReflector<SimpleSoftOMXComponent>(this)),---注意这个mHandle的参数,其中 SimpleSoftOMXComponent做为这个mHandle的投递目标,也就是消息将有 SimpleSoftOMXComponent处理。最终,消息会被投递到mLooper中的mEventQueue,并在消息循环(也就是mLooper.loop()函数中,被deliverMessage,然后被相应的hanler处理,也就是SimpleSoftOMXComponent::onMessageReceived函数)。
在来看一个继承关系图。
这个继承关系图,也许能说明一些问题。最右边的是具体的软件编/解码模块的实现的代码,在openmanx框架中,为了实现动态绑定,这些moudle最终会被编译成libstagefright_soft_XXXX.so。具体的编译步骤,可以去看相关路径下的Android.mk文件。可以说明一点的是,这些libstagefright_soft_XXXX.so是首先由一些编解码的srcfile编译出一个类似于libstagefright_m4vh263dec的静态库,然后这个静态库再被编译进一个.so里。
在这个继承关系图上,位于中间的SimpleSoftOMXComponent,完成了大部分的工作,它负责sendCommand的同时又要将一些反馈信息notify到其父类SoftOMXCodec来处理。这些反馈的信息包括,组件状态的变化,ports的状态的变化等等。父类SoftOMXComponent来处理的notify的信息,其主要的工作是,找到具体的handler然后调用适当的CallBacks。
关于组建的结构再来看一张图,下面是一张组件的模型图:
说的简单一点,command从组件的外部进来,在组件内进行一系列的传递和处理(组件内部自己处理)之后,再将反馈信息传回组件外部,传递给OMXCodec框架层。
说点废话,把时序图再贴一次:
首先,可以明确一点的是,整个stagefright框架都是事件驱动模式的。上面的时序图主要描述了,收到onPrepareAsyncEvent时间后,OMX框架是如何是如何建立自己的编解码组件。上面的时序图中,要明确两点 1,事件驱动模式是异步的 2,时序图的末端 CallbackDispatcher也是异步分派的。从上面的时序图中还有一点没有办法看出来。就是对应于具体的编解码组件,编解码的过程时候时候发生。下面就这个问题,展开讨论。////////////////////////////////////////下面的研究将围绕三个问题/////////////////////////////////////1,待解码的原始数据问题 2,具体编解码组件是如何完成编解码工作的 3,解码之后的数据处理问题
以上的三个问题,在我的《数据流向分析》中有介绍。
OK,备忘做完了,还是那句话,菜鸟们请批判性的看,comments are very welcome.
- Android_ics openmax in stagefright 学习记录------2
- Android_ics openmax in stagefright 学习记录------2
- Android_ics openmax in stagefright 学习记录------1
- Android_ics openmax in stagefright 学习记录------1
- Stagefright (2) - 和OpenMAX的運作
- Stagefright (2) - 和OpenMAX的運作
- stagefright之OpenMax实现
- stagefright 的OpenMax
- stagefright,OpenMax框架
- Android-StageFright之OpenMAX的实现
- Android-StageFright之OpenMAX的实现
- Stagefright 之 与Openmax IL一起工作
- StageFright学习笔记(2)
- stagefright框架(二)- 和OpenMAX的運作
- stagefright框架(二)- 和OpenMAX的運作
- stagefright框架(二)- 和OpenMAX的運作
- stagefright框架(二)- 和OpenMAX的運作
- stagefright框架(二)- 和OpenMAX的運作
- 让你访问google.com的方法(转)
- 爱立信实验室实习感想(二)
- 数组指针与指针数组
- 计算几何题目推荐
- WORA预言的云计算未来
- Android_ics openmax in stagefright 学习记录------2
- VC UI界面库大集合[转]
- window.open打开新窗口
- 黑马程序员_Java学习日记7_String总结
- winfrom(C#) Post提交(带参数),返回值
- LibJingle连接openfire 错误
- 提高WebService性能大数据量网络传输处理
- 面向对象与过程的区别
- poi-3.8-20120326.jar下载地址