{"id":617,"date":"2013-06-25T17:33:40","date_gmt":"2013-06-25T09:33:40","guid":{"rendered":"http:\/\/guoh.ai\/lifelog\/?p=617"},"modified":"2013-08-01T01:33:21","modified_gmt":"2013-07-31T17:33:21","slug":"interaction-between-stagefright-and-codec","status":"publish","type":"post","link":"https:\/\/guoh.ai\/lifelog\/2013\/06\/interaction-between-stagefright-and-codec\/","title":{"rendered":"Stagefright\u548ccodec\u7684\u4ea4\u4e92"},"content":{"rendered":"<p>Stagefright\u548ccodec\u7684\u4ea4\u4e92\u662f\u901a\u8fc7<a href=\"http:\/\/www.khronos.org\/openmax\/\" target=\"_blank\">OpenMAX<\/a> IL\u6765\u5b8c\u6210\u7684\u3002<\/p>\n<p>OpenMAX IL\u7684\u89c4\u8303\u5934\u6587\u4ef6\u4f4d\u4e8e<br \/>\n\/path\/to\/aosp\/frameworks\/native\/include\/media\/openmax<\/p>\n<p>\u6982\u8ff0\u4e0bOpenMAX IL\uff0c\u5b83\u5305\u62ec\u5ba2\u6237\u7aef(Client)\uff0c\u7ec4\u4ef6(Component)\uff0c\u7aef\u53e3(Port)\uff0c\u96a7\u9053\u5316(Tunneled)\u3002<br \/>\nClient\u662f\u8c03\u7528Component\u7684\u5bf9\u8c61\uff0cPort\u548cTunneled\u662fComponent\u4e4b\u95f4\u901a\u4fe1\u7684\u65b9\u5f0f\uff0cComponent\u4e4b\u95f4\u8fd8\u53ef\u4ee5\u5b58\u5728\u79c1\u6709\u7684\u901a\u4fe1\u65b9\u5f0f\u3002<br \/>\n\u7ec4\u4ef6(Component)\u7684\u529f\u80fd\u548c\u5176\u5b9a\u4e49\u7684\u7aef\u53e3\u7c7b\u578b\u5bc6\u5207\u76f8\u5173\uff0c\u901a\u5e38\u60c5\u51b5\u4e0b\uff1a\u53ea\u6709\u4e00\u4e2a\u8f93\u51fa\u7aef\u53e3\u7684\uff0c\u4e3aSource\u7ec4\u4ef6\uff1b\u53ea\u6709\u4e00\u4e2a\u8f93\u5165\u7aef\u53e3\u7684\uff0c\u4e3aSink\u7ec4\u4ef6\uff1b\u6709\u591a\u4e2a\u8f93\u5165\u7aef\u53e3\uff0c\u4e00\u4e2a\u8f93\u51fa\u7aef\u53e3\u7684\u4e3aMux\u7ec4\u4ef6\uff1b\u6709\u4e00\u4e2a\u8f93\u5165\u7aef\u53e3\uff0c\u591a\u4e2a\u8f93\u51fa\u7aef\u53e3\u7684\u4e3aDeMux\u7ec4\u4ef6\uff1b\u8f93\u5165\u8f93\u51fa\u7aef\u53e3\u5404\u4e00\u4e2a\u7ec4\u4ef6\u7684\u4e3a\u4e2d\u95f4\u5904\u7406\u73af\u8282\uff0c\u8fd9\u662f\u6700\u5e38\u89c1\u7684\u7ec4\u4ef6\u3002<\/p>\n<p>\u5728Android 2.2\u4ee5\u53ca\u4e4b\u540e\uff0cStagefright\u662f\u4f5c\u4e3aOpenMAX IL\u7684\u4e0a\u5c42\u5b58\u5728\u7684\uff0c\u5b83\u8ddfOpenMAX IL\u5bf9\u63a5\uff0c\u7136\u540eOpenMAX IL\u53c8\u5c01\u88c5\u4e86\u5177\u4f53\u7684codec\u3002<\/p>\n<p>\u4e4b\u524d\u6211\u6709\u5728<a href=\"http:\/\/guoh.ai\/lifelog\/2013\/06\/android-mediarecorder-architecture\/\" target=\"_blank\">http:\/\/guoh.ai\/lifelog\/2013\/06\/android-mediarecorder-architecture\/<\/a>\u5206\u6790\u8fc7StagefrightRecorder\uff0c\u5f53\u65f6\u8ddfcodec\u7684\u96c6\u6210\u6211\u6ca1\u6709\u4ed4\u7ec6\u5206\u6790\u3002<\/p>\n<p>\u8fd9\u7bc7\u6587\u7ae0\u4f1a\u8be6\u7ec6\u5206\u6790\u4e0b\u8fd9\u4e2a\u903b\u8f91\u8fc7\u7a0b\u3002<\/p>\n<p>\u9996\u5148\u6211\u4eec\u4f1a\u78b0\u5230\u51e0\u4e2a\u5173\u952e\u7684\u7c7b\uff0c\u7b2c\u4e00\u4e2a\u5c31\u662fOMX\uff0c\u5e76\u4e14\u5b83\u7684\u6784\u9020\u65b9\u6cd5\u5f53\u4e2d\u4f1a\u53bb\u521b\u5efa\u4e00\u4e2aOMXMaster\uff0c\u7ee7\u7eed\u8ffd\u8e2a\u4e0b\uff0c\u53d1\u73b0OMXMaster\u6b63\u5982\u5176\u540d\u5b57\u6240\u793a\uff0c\u662f\u4e00\u4e2a\u7ba1\u7406\u8005\u89d2\u8272\u3002<br \/>\nOMXMaster\u4f5c\u4e3a\u7ba1\u7406\u8005\uff0c\u6bcf\u6dfb\u52a0\u4e00\u4e2aplugin\u8fdb\u6765\uff0c\u90fd\u4f1a\u8bb0\u5f55\u5728<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">KeyedVector&lt;String8, OMXPluginBase *&gt; mPluginByComponentName; \/\/ \u91cd\u590d\u540d\u5b57\u7684codec\u4e0d\u4f1a\u518d\u8ba9\u5176\u52a0\u8fdb\u6765\uff0c\u4e5f\u5c31\u662f\u5b83\u4f1a\u53bb\u786e\u5b9a\u8be5plugin\u652f\u6301\u591a\u5c11codec\uff0c\u7136\u540e\u8bb0\u5f55\u4e0b\u6765\r\nList&lt;OMXPluginBase *&gt; mPlugins; \/\/ \u4e3b\u8981\u8d1f\u8d23\u91ca\u653e\u5185\u5b58(\u4e0d\u4e0e\u4e1a\u52a1\u76f8\u5173\uff0c\u53ea\u7ba1\u6709\u6dfb\u52a0\u8fdb\u6765\u7684plugin)<\/pre>\n<p>OMXMaster\u5230\u5e95\u4f1a\u52a0\u591a\u5c11\u4e2aOMXPlugin\u8fdb\u6765\uff1f<br \/>\n\u4ee5\u53ca\u5230\u5e95\u4f1a\u6709\u591a\u5c11\u4e2aOMXMaster\uff1f<br \/>\n\u6709\u591a\u5c11\u4e2aOMX\u5c31\u6709\u591a\u5c11\u4e2aOMXMaster\uff0c\u90a3\u6709\u591a\u5c11\u4e2aOMX\u5462\uff1f<br \/>\n\u53ea\u6709\u4e00\u4e2a\uff0c\u53c2\u89c1<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">sp&lt;IOMX&gt; MediaPlayerService::getOMX() {\r\n    Mutex::Autolock autoLock(mLock);\r\n\r\n    if (mOMX.get() == NULL) {\r\n        mOMX = new OMX;\r\n    }\r\n\r\n    return mOMX;\r\n}<\/pre>\n<p>\u90a3\u4f1a\u6709\u591a\u5c11\u4e2aOMXPlugin\u5462\uff1f\u3002<\/p>\n<p>\u4e00\u4e2aSoftOMXPlugin\uff0c\u5f53\u4e2d\u53ef\u4ee5\u52a0\u8f7d\u5f88\u591acodec(s)\u8fdb\u6765<br \/>\n\/path\/to\/aosp\/frameworks\/av\/media\/libstagefright\/codecs\/<br \/>\n\u6709\u591a\u5c11soft codec(s)\u90fd\u5728\u4e0a\u9762\u8fd9\u4e2a\u76ee\u5f55<\/p>\n<p>\u8fd9\u91cc\u9700\u8981\u8bf4\u660e\u7684\u662f\u771f\u5b9e\u7684codec\u7684\u7c7b\u7ed3\u6784\uff0c\u4ee5FLAC\u4e3a\u4f8b\u5b50(\u7bad\u5934\u7684\u65b9\u5411\u4e3a\u7c7b\u7ee7\u627f\u7684\u65b9\u5411)<br \/>\nSoftFlacEncoder -> SimpleSoftOMXComponent -> SoftOMXComponent\uff0cSoftOMXComponent\u628aOpenMAX IL\u5b9a\u4e49\u7684\u7ec4\u4ef6\u5c01\u88c5\u6210\u4e00\u4e2aC++\u7c7b\uff0c\u91cc\u9762\u6709\u7ed1\u5b9a\u7ec4\u4ef6\u64cd\u4f5c\u7684\u65b9\u6cd5\uff0c\u4f46\u662f\u5b83\u5b9e\u90fd\u662f\u4ee5stub\u65b9\u5f0f\u5b9e\u73b0\u7684\uff0c\u4e5f\u5c31\u662f\u8bf4\u5177\u4f53\u7684\u5b9e\u73b0\u5728\u5176\u5b50\u7c7b\u3002<br \/>\nSimpleSoftOMXComponent\u63d0\u4f9b\u4e00\u4e2a\u7528\u4e8e\u6d88\u606f\u4f20\u9012\u7684ALooper\u548cAHandlerReflector\uff0c\u5b9e\u73b0\u4e86\u6bd4\u5982sendCommand\uff0cemptyThisBuffer\u548cfillThisBuffer\u8fd9\u4e09\u4e2a\u5f02\u6b65\u65b9\u6cd5(\u4e3a\u4ec0\u4e48\u53ea\u6709\u8fd9\u4e09\u4e2a\u662f\u5f02\u6b65\uff0c\u56e0\u4e3aOpenMAX IL\u7684\u89c4\u8303\u8981\u6c42\u8fd9\u4e09\u4e2a\u662fnon-blocking\u7684\uff0c\u5728\u6211\u4eec\u8fd9\u91cc\u5b9e\u73b0\u7684\u4e5f\u5c31\u662f\u901a\u8fc7looper\/handler\u53d1\u9001\u5904\u7406\u6d88\u606f)\uff0c\u4ee5\u53causeBuffer\uff0callocateBuffer\u548cfreeBuffer\u7b49\u7b49\u4e00\u4e9b\u5176\u4ed6\u65b9\u6cd5\u3002<br \/>\n\u8fd9\u6837OMXCodec\u5f53\u4e2d\u9488\u5bf9OpenMAX IL\u7ec4\u4ef6\u7684\u4e00\u4e2a\u64cd\u4f5c\u5c31\u4f1a\u901a\u8fc7IOMX\uff0c\u8fdb\u800c\u5230OMXNodeInstance\uff0c\u6700\u7ec8\u8fdb\u5165\u6211\u4eecSoftOMXComponent\u91cc\u9762\uff0c\u521a\u521a\u6211\u4eec\u6709\u8bb2\u8fc7\u65b9\u6cd5\u5177\u4f53\u5b9e\u73b0\u662f\u5728\u5176\u5b50\u7c7b\uff0c\u8fd9\u6837\u53ea\u8981\u627e\u5230\u5bf9\u5e94\u7684\u5730\u65b9\u5c31\u53ef\u4ee5\u4e86\u3002<\/p>\n<p>\u4e0b\u9762\u7684\u8fd9\u4e00\u6bb5\u5b9e\u4f8b\u4ee3\u7801\u5f88\u6e05\u6670\uff0c\u4ee5sendCommand\u4e3a\u4f8b\u5b50<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">status_t OMXCodec::init() {\r\n    \/\/ mLock is held.\r\n    ...\r\n    err = mOMX-&gt;sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);\r\n    ...\r\n}<\/pre>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">status_t OMX::sendCommand(\r\n        node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {\r\n    return findInstance(node)-&gt;sendCommand(cmd, param);\r\n}<\/pre>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">status_t OMXNodeInstance::sendCommand(\r\n        OMX_COMMANDTYPE cmd, OMX_S32 param) {\r\n    Mutex::Autolock autoLock(mLock);\r\n\r\n    OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); \/\/ \u6ce8\u610f\u8fd9\u4e2a\u5b8f\u7684\u5b9a\u4e49\uff0c\u5b9e\u9645\u5c31\u662f\u53bb\u8c03\u7528\u7ec4\u4ef6\u7684SendCommand\u65b9\u6cd5\r\n    return StatusFromOMXError(err);\r\n}<\/pre>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n\/** Send a command to the component.  This call is a non-blocking call.\r\n    The component should check the parameters and then queue the command\r\n    to the component thread to be executed.  The component thread shall \r\n    send the EventHandler() callback at the conclusion of the command. \r\n    This macro will go directly from the application to the component (via\r\n    a core macro).  The component will return from this call within 5 msec.\r\n    \r\n    When the command is &quot;OMX_CommandStateSet&quot; the component will queue a\r\n    state transition to the new state idenfied in nParam.\r\n    \r\n    When the command is &quot;OMX_CommandFlush&quot;, to flush a port&#039;s buffer queues,\r\n    the command will force the component to return all buffers NOT CURRENTLY \r\n    BEING PROCESSED to the application, in the order in which the buffers \r\n    were received.\r\n    \r\n    When the command is &quot;OMX_CommandPortDisable&quot; or \r\n    &quot;OMX_CommandPortEnable&quot;, the component&#039;s port (given by the value of\r\n    nParam) will be stopped or restarted. \r\n    \r\n    When the command &quot;OMX_CommandMarkBuffer&quot; is used to mark a buffer, the\r\n    pCmdData will point to a OMX_MARKTYPE structure containing the component\r\n    handle of the component to examine the buffer chain for the mark.  nParam1\r\n    contains the index of the port on which the buffer mark is applied.\r\n\r\n    Specification text for more details. \r\n    \r\n    @param &#x5B;in] hComponent\r\n        handle of component to execute the command\r\n    @param &#x5B;in] Cmd\r\n        Command for the component to execute\r\n    @param &#x5B;in] nParam\r\n        Parameter for the command to be executed.  When Cmd has the value \r\n        OMX_CommandStateSet, value is a member of OMX_STATETYPE.  When Cmd has \r\n        the value OMX_CommandFlush, value of nParam indicates which port(s) \r\n        to flush. -1 is used to flush all ports a single port index will \r\n        only flush that port.  When Cmd has the value &quot;OMX_CommandPortDisable&quot;\r\n        or &quot;OMX_CommandPortEnable&quot;, the component&#039;s port is given by \r\n        the value of nParam.  When Cmd has the value &quot;OMX_CommandMarkBuffer&quot;\r\n        the components pot is given by the value of nParam.\r\n    @param &#x5B;in] pCmdData\r\n        Parameter pointing to the OMX_MARKTYPE structure when Cmd has the value\r\n        &quot;OMX_CommandMarkBuffer&quot;.     \r\n    @return OMX_ERRORTYPE\r\n        If the command successfully executes, the return code will be\r\n        OMX_ErrorNone.  Otherwise the appropriate OMX error will be returned.\r\n    @ingroup comp\r\n *\/\r\n#define OMX_SendCommand(                                    \\\r\n         hComponent,                                        \\\r\n         Cmd,                                               \\\r\n         nParam,                                            \\\r\n         pCmdData)                                          \\\r\n     ((OMX_COMPONENTTYPE*)hComponent)-&gt;SendCommand(         \\\r\n         hComponent,                                        \\\r\n         Cmd,                                               \\\r\n         nParam,                                            \\\r\n         pCmdData)                          \/* Macro End *\/\r\n<\/pre>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">OMX_ERRORTYPE SimpleSoftOMXComponent::sendCommand(\r\n        OMX_COMMANDTYPE cmd, OMX_U32 param, OMX_PTR data) {\r\n    CHECK(data == NULL);\r\n\r\n    sp&lt;AMessage&gt; msg = new AMessage(kWhatSendCommand, mHandler-&gt;id());\r\n    msg-&gt;setInt32(&quot;cmd&quot;, cmd);\r\n    msg-&gt;setInt32(&quot;param&quot;, param);\r\n    msg-&gt;post();\r\n\r\n    return OMX_ErrorNone;\r\n}<\/pre>\n<p>\u5f53\u7136\u8fd9\u662f\u5f02\u6b65\u7684\u8bdd\uff0c\u5c31\u8fd8\u4f1a\u6709\u9700\u8981\u5f02\u6b65\u6267\u884c\u7684\u5904\u7406\u51fd\u6570\u56de\u6765\uff0c\u6bd4\u5982\u5728onMessageReceived\u65b9\u6cd5\u5f53\u4e2d\u5c31\u6709\u7c7b\u578b\u4e3akWhatSendCommand\uff0ckWhatEmptyThisBuffer\u548ckWhatFillThisBuffer\u7684\u6d88\u606f\uff0c\u5206\u522b\u4f1a\u53bb\u8c03\u7528\u81ea\u5df1\u7684\u5904\u7406\u65b9\u6cd5\u3002<br \/>\n\u5176\u4ed6\u540c\u6b65\u7684\u65b9\u6cd5\u8c03\u7528\u8fc7\u7a0b\u7c7b\u4f3c\uff0c\u8fd9\u91cc\u6211\u4eec\u5c31\u4e0d\u5177\u4f53\u518d\u8bf4\uff0c\u5bf9\u7167\u4ee3\u7801\u770b\u770b\u5e94\u8be5\u5c31\u80fd\u7406\u89e3\uff01<\/p>\n<p>\u8fd8\u6709\u4e00\u70b9\u9700\u8981\u63d0\u4e00\u4e0b\uff0c\u5c31\u662f\u5177\u4f53codec\u88ab\u521b\u5efa\u7684\u65b9\u5f0f\u548c\u65f6\u95f4\uff0csoft codec\u662f\u5728SoftOMXPlugin::makeComponentInstance\u5f53\u4e2d\u901a\u8fc7\u8c03\u7528\u8be5codec\u7684createSoftOMXComponent\u65b9\u6cd5\u6765\u521b\u5efa\u51fa\u6765\u7684\uff0c\u6362\u53e5\u8bdd\u8bf4\u6211\u4eec\u7684codec\u5b9e\u73b0\u5fc5\u987b\u8981\u5305\u542b\u8fd9\u6837\u540d\u5b57\u7684\u4e00\u4e2a\u65b9\u6cd5\uff0c\u5bf9\u4e8eFLAC\u5c31\u662f<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">android::SoftOMXComponent *createSoftOMXComponent(\r\n        const char *name, const OMX_CALLBACKTYPE *callbacks,\r\n        OMX_PTR appData, OMX_COMPONENTTYPE **component) {\r\n    return new android::SoftFlacEncoder(name, callbacks, appData, component);\r\n}<\/pre>\n<p>\u4f1a\u6709\u591a\u5c11\u4e2aVendor plugin(\u5373<strong>libstagefrighthw<\/strong>)?<br \/>\n\u7b54\u6848\u4e5f\u662f\u4e00\u4e2a\uff0c\u4f46\u662f\u5b83\u540c\u6837\u4e5f\u5305\u542b\u6709\u5f88\u591a\u4e2acodec(s)\u8fdb\u6765\uff0c\u4ee5TI\u7684HW\u4e3a\u4f8b\u5b50\uff1a<br \/>\nTIOMXPlugin(\u5373Vendor plugin)\u5728\/path\/to\/aosp\/hardware\/ti\/omap4xxx\/libstagefrighthw\/\u8fd9\u91cc<br \/>\n\u4f46\u662f\u5177\u4f53\u7684\u5b9e\u73b0\u5728\/path\/to\/aosp\/hardware\/ti\/omap4xxx\/domx\/omx_core\/(\u5373libOMX_Core.so)\u5f53\u4e2d<br \/>\n\u5047\u8bbe\u8981\u5b9e\u4f8b\u5316\u4e00\u4e2acodec\uff0c\u5c31\u9700\u8981\u7ecf\u8fc7\u5982\u4e0b\u6b65\u9aa4\uff1a<br \/>\nTIOMXPlugin.cpp(makeComponentInstance) -> OMX_Core_Wrapper.c(TIOMX_GetHandle) -> OMX_Core.c(OMX_GetHandle) -> \u52a8\u6001\u53bbload\u6307\u5b9a\u7684codec\u7684so\u6863\u6848\uff0c\u7136\u540e\u8c03\u7528\u5b83\u7684\u521d\u59cb\u5316\u65b9\u6cd5(OMX_ComponentInit)\uff0c\u81f3\u4e8e\u8fd9\u4e2a\u65b9\u6cd5\u540d\uff0c\u5e94\u8be5\u662f\u9075\u5faa\u89c4\u8303\u5f97\u6765\u7684(\u89c4\u8303\u4e0a\u6709\u5199\u8fd9\u4e48\u53e5\u8bdd\uff0c\u6709\u8fd9\u4e48\u4e00\u4e2aerror msg code)\u3002<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\/** The component specified did not have a &quot;OMX_ComponentInit&quot; or\r\n  &quot;OMX_ComponentDeInit entry point *\/\r\nOMX_ErrorInvalidComponent = (OMX_S32) 0x80001004,<\/pre>\n<p>\u5176\u652f\u6301\u7684codec(s)\u5728\/path\/to\/aosp\/hardware\/ti\/omap4xxx\/domx\/omx_proxy_component\/<br \/>\n\u5f53\u7136codec\u6700\u7ec8\u7684\u5b9e\u73b0\u53ef\u80fd\u8fd8\u662f\u5728\u5176\u4ed6\u5730\u65b9\uff01<\/p>\n<p>\u4ee5\u4e0b\u8fd9\u4e9b\u65b9\u6cd5\u90fd\u662fOpenMAX IL\u6240\u5b9a\u4e49\u7684\u4e8eOMX Core\u6709\u5173\u7684\u6807\u51c6\u65b9\u6cd5\uff0c\u8be6\u89c1OMX_Core.h\uff0cTI\u5728OMX_Core.c\u5f53\u4e2d\u6709\u53bb\u5b9e\u73b0\u8fd9\u4e9b\u65b9\u6cd5\uff0c\u8fd9\u4e9b\u53ef\u4ee5\u8bf4\u662f\u7ba1\u7406OpenMAX IL\u8fd9\u4e00\u5c42\u6240\u5c01\u88c5\u7684Component\u7684\u63a5\u53e3\uff0c\u5f53\u7136\u5305\u62ec\u81ea\u8eab\u7684\u751f\u547d\u5468\u671f\u7684\u7ba1\u7406\uff0c\u4ee5\u53caComponent\u4e4b\u95f4\u7684\u6c9f\u901a\u3002<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">OMX_API OMX_ERRORTYPE OMX_Init\r\nOMX_API OMX_ERRORTYPE OMX_Deinit\r\nOMX_API OMX_ERRORTYPE OMX_ComponentNameEnum\r\nOMX_API OMX_ERRORTYPE OMX_GetHandle\r\nOMX_API OMX_ERRORTYPE OMX_FreeHandle\r\nOMX_API OMX_ERRORTYPE OMX_SetupTunnel\r\nOMX_API OMX_ERRORTYPE OMX_GetContentPipe\r\nOMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole\r\nOMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent<\/pre>\n<p>\u4e5f\u5c31\u662f\u8bf4OMX\u662f\u64cd\u4f5c\u6240\u6709codec\u7684\u7a97\u53e3\uff0c\u5b83\u900f\u8fc7OMXMaster\u6765\u7ba1\u7406Soft\/Vendor plugin\uff0c\u6bcf\u4e2aplugin\u5f53\u4e2d\u6709\u5c5e\u4e8e\u81ea\u5df1\u7684codec(s)\u3002<br \/>\n\u6bd4\u5982\u5178\u578b\u7684\uff0cOMX\u6709allocateNode\u8fd9\u4e2a\u65b9\u6cd5\uff0c\u8fd9\u662f\u589e\u52a0codec\u65f6\u9700\u8981\u7684\uff0c\u5f53\u7136\u5b83\u5b9e\u8d28\u4e0a\u662f\u53bb\u8c03\u7528OMXMaster -> OMXPlugin -> OMX_Core -> \u7279\u5b9a\u7684codec\u7684\u5b9e\u4f8b\u5316\u65b9\u6cd5\u3002<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">status_t OMX::allocateNode(\r\n        const char *name, const sp&lt;IOMXObserver&gt; &amp;observer, node_id *node) {\r\n    Mutex::Autolock autoLock(mLock);\r\n\r\n    *node = 0;\r\n\r\n    OMXNodeInstance *instance = new OMXNodeInstance(this, observer);\r\n\r\n    OMX_COMPONENTTYPE *handle; \/\/ \u58f0\u660e\u4e00\u4e2aOMX_COMPONENTTYPE\u6307\u9488\r\n\r\n    \/\/ \u63a5\u7740makeComponentInstance\u521b\u5efa\u51fa\u6765\uff0c\u53cc\u6307\u9488OUT\u4f20\u503c\r\n    \/\/ \u6700\u7ec8\u4f1a\u53d1\u73b0\u5728codec\u5f53\u4e2d\u4f1a\u53bb\u8c03\u7528\u8fd9\u6837\u4e00\u4e2a\u65b9\u6cd5(\u5bf9\u4e8eTI\u7684HW\uff0c\u8fd9\u4e2a\u65b9\u6cd5\u4f4d\u4e8eomx_proxy_common.c\u5f53\u4e2d)\r\n    \/\/ \/*Calling Proxy Common Init() *\/\r\n\t\/\/ eError = OMX_ProxyCommonInit(hComponent);\r\n\t\/\/ \u5b83\u4f1a\u53bb\u521d\u59cb\u5316OMX_COMPONENTTYPE\u7684\u5404\u4e2a\u5c5e\u6027\uff0c\u65b9\u6cd5\uff0c\u4f8b\u5982OMX_COMPONENTTYPE::SetCallbacks\u7b49\u7b49\r\n\r\n    OMX_ERRORTYPE err = mMaster-&gt;makeComponentInstance(\r\n            name, &amp;OMXNodeInstance::kCallbacks,\r\n            instance, &amp;handle);\r\n\r\n    if (err != OMX_ErrorNone) {\r\n        ALOGV(&quot;FAILED to allocate omx component &#039;%s&#039;&quot;, name);\r\n\r\n        instance-&gt;onGetHandleFailed();\r\n\r\n        return UNKNOWN_ERROR;\r\n    }\r\n\r\n    *node = makeNodeID(instance);\r\n    mDispatchers.add(*node, new CallbackDispatcher(instance));\r\n\r\n    instance-&gt;setHandle(*node, handle);\r\n\r\n    mLiveNodes.add(observer-&gt;asBinder(), instance);\r\n    observer-&gt;asBinder()-&gt;linkToDeath(this);\r\n\r\n    return OK;\r\n}<\/pre>\n<p>\u6709\u4e24\u70b9\u503c\u5f97\u6ce8\u610f\u7684\u662f<br \/>\na)<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">status_t OMXClient::connect() {\r\n    sp&lt;IServiceManager&gt; sm = defaultServiceManager();\r\n    sp&lt;IBinder&gt; binder = sm-&gt;getService(String16(&quot;media.player&quot;));\r\n    sp&lt;IMediaPlayerService&gt; service = interface_cast&lt;IMediaPlayerService&gt;(binder);\r\n\r\n    \/\/ defaultServiceManager(\u4f4d\u4e8e\/path\/to\/aosp\/frameworks\/native\/include\/binder\/IServiceManager.h)\r\n    \/\/ \u8fd9\u6837\u8c03\u7528\u5c31\u8ddf\u672c\u5730\u7684\u4e00\u4e2aservice\u6307\u9488\u6765\u8c03\u7528getOMX\u662f\u4e00\u6837\u7684\uff0c\u56e0\u4e3a\u672c\u6765StatefrightRecorder\u662f\u5728MediaPlayerService\u5f53\u4e2dnew\u51fa\u6765\u7684\r\n    \/\/ \u8fd9\u4e2a\u6211\u4eec\u5728\u4e4b\u524d\u7684\u7814\u7a76\u8ba8\u8bba\u4e2d\u505a\u8fc7\u5b9e\u9a8c\uff0c\u8be6\u7ec6\u53c2\u89c1http:\/\/guoh.ai\/lifelog\/2013\/06\/sample-of-customized-service-on-android-platform\/\u600e\u6837\u4e3aAndroid\u6dfb\u52a0\u4e00\u4e2a\u7cfb\u7edf\u7ea7\u670d\u52a1\r\n\r\n    CHECK(service.get() != NULL);\r\n\r\n    mOMX = service-&gt;getOMX(); \/\/ BnOMX\r\n    CHECK(mOMX.get() != NULL);\r\n\r\n    \/\/ \u4ec0\u4e48\u60c5\u51b5\u4f1a\u6709\u4e0d\u662f\u5728\u672c\u5730\uff0c\u8c8c\u4f3cOMX\u662f\u5728MediaPlayerService\u5f53\u4e2dnew\u51fa\u6765\u7684\uff0c\r\n    \/\/ OMXClient\u662f\u5728StagefrightRecorder\u5f53\u4e2dnew\u51fa\u6765\u7684\uff0c\u800cStagefrightRecorder\u53c8\u662f\u5728MediaPlayerService\u5f53\u4e2dnew\u51fa\u6765\r\n    \/\/ \u6240\u4ee5\u4ec0\u4e48\u60c5\u51b5\u4e0b\u4f1a\u8d70\u5230\u5982\u4e0b\u7684\u8fd9\u4e2ausing client-side OMX mux\u5f53\u4e2d\u53bb(MuxOMX\u4f4d\u4e8eOMXClient.cpp\u5f53\u4e2d)\uff1f\r\n    if (!mOMX-&gt;livesLocally(NULL \/* node *\/, getpid())) {\r\n        ALOGI(&quot;Using client-side OMX mux.&quot;);\r\n        mOMX = new MuxOMX(mOMX); \/\/ \u7ee7\u627f\u81eaIOMX\r\n    }\r\n\r\n    return OK;\r\n}<\/pre>\n<p>\u5bb9\u6613\u770b\u51faOMXClient\u662f\u83b7\u53d6OMX\u7684\u7a97\u53e3<\/p>\n<p>b)<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">sp&lt;MediaSource&gt; encoder = OMXCodec::Create(\r\n        client.interface(), enc_meta,\r\n        true \/* createEncoder *\/, cameraSource,\r\n        NULL, encoder_flags);<\/pre>\n<p>\u90a3OMXCodec\/<br \/>\n\/path\/to\/aosp\/frameworks\/av\/include\/media\/stagefright<br \/>\n\/path\/to\/aosp\/frameworks\/av\/media\/libstagefright<br \/>\nOMXNodeInstance<br \/>\n\/path\/to\/aosp\/frameworks\/av\/media\/libstagefright\/include<br \/>\n\/path\/to\/aosp\/frameworks\/av\/media\/libstagefright\/omx<br \/>\n\u662f\u505a\u4ec0\u4e48\u7684\uff1f<br \/>\nOMXCodec\uff0cOMXCodecObserver\u548cOMXNodeInstance\u662f\u4e00\u4e00\u5bf9\u5e94\u7684\uff0c<br \/>\n\u7b80\u5355\u7684\u53ef\u4ee5\u7406\u89e3\u5b83\u4eec3\u4e2a\u6784\u6210\u4e86OpenMAX IL\u7684\u4e00\u4e2aComponent\uff0c\u6bcf\u4e00\u4e2anode\u5c31\u662f\u4e00\u4e2acodec\u5728OMX\u670d\u52a1\u7aef\u7684\u6807\u8bc6\u3002<br \/>\n\u5f53\u7136\u8fd8\u6709CallbackDispatcher\uff0c\u7528\u4e8e\u5904\u7406codec\u8fc7\u6765\u7684\u6d88\u606f\uff0c\u901a\u8fc7\u5b83\u7684post\/loop\/dispatch\u6765\u53d1\u8d77\u63a5\u6536\uff0c\u6700\u7ec8\u900f\u8fc7IOMX::onMessage -> OMXNodeInstance::onMessage -> OMXCodecObserver::onMessage -> OMXCodec::on_message\u4e00\u8def\u5f80\u4e0a\uff0c\u5f53\u7136\u6d88\u606f\u7684\u6765\u6e90\u662f\u56e0\u4e3a\u6211\u4eec\u6709\u5411codec\u6ce8\u518cOMXNodeInstance::kCallbacks\uff0c\u8bf7\u770b<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">status_t OMX::allocateNode(\r\n        const char *name, const sp&lt;IOMXObserver&gt; &amp;observer, node_id *node) {\r\n    ...\r\n    OMX_ERRORTYPE err = mMaster-&gt;makeComponentInstance(\r\n            name, &amp;OMXNodeInstance::kCallbacks,\r\n            instance, &amp;handle);\r\n    ...\r\n    return OK;\r\n}<\/pre>\n<p>kCallbacks\u5305\u542b3\u79cd\u4e8b\u4ef6<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {\r\n    &amp;OnEvent, &amp;OnEmptyBufferDone, &amp;OnFillBufferDone\r\n};<\/pre>\n<p>\u5b83\u4eec\u5206\u522b\u90fd\u4f1a\u8c03\u7528\u5230\u81ea\u5df1owner\u7684OnEvent\/OnEmptyBufferDone\/OnFillBufferDone<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\/\/ static\r\nOMX_ERRORTYPE OMXNodeInstance::OnEvent(\r\n        OMX_IN OMX_HANDLETYPE hComponent,\r\n        OMX_IN OMX_PTR pAppData,\r\n        OMX_IN OMX_EVENTTYPE eEvent,\r\n        OMX_IN OMX_U32 nData1,\r\n        OMX_IN OMX_U32 nData2,\r\n        OMX_IN OMX_PTR pEventData) {\r\n    OMXNodeInstance *instance = static_cast&lt;OMXNodeInstance *&gt;(pAppData);\r\n    if (instance-&gt;mDying) {\r\n        return OMX_ErrorNone;\r\n    }\r\n    return instance-&gt;owner()-&gt;OnEvent(\r\n            instance-&gt;nodeID(), eEvent, nData1, nData2, pEventData);\r\n}<\/pre>\n<p>\u800cowner\u76f8\u5e94\u7684\u53c8\u4f1a\u8c03\u7528\u81ea\u5df1dispatcher\u7684post\u65b9\u6cd5\uff0c\u5982\u4e0b\uff1a<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">OMX_ERRORTYPE OMX::OnEvent(\r\n        node_id node,\r\n        OMX_IN OMX_EVENTTYPE eEvent,\r\n        OMX_IN OMX_U32 nData1,\r\n        OMX_IN OMX_U32 nData2,\r\n        OMX_IN OMX_PTR pEventData) {\r\n    ALOGV(&quot;OnEvent(%d, %ld, %ld)&quot;, eEvent, nData1, nData2);\r\n\r\n    omx_message msg;\r\n    msg.type = omx_message::EVENT;\r\n    msg.node = node;\r\n    msg.u.event_data.event = eEvent;\r\n    msg.u.event_data.data1 = nData1;\r\n    msg.u.event_data.data2 = nData2;\r\n\r\n    findDispatcher(node)-&gt;post(msg);\r\n\r\n    return OMX_ErrorNone;\r\n}<\/pre>\n<p>\u8fd9\u6837\u6240\u6709\u7684\u4e8b\u4ef6\u90fd\u4e32\u8d77\u6765\u4e86\uff0c\u6d88\u606f\u6709\u6765\u6e90\uff0c\u6709\u6700\u7ec8\u7684\u53bb\u5904\uff01<\/p>\n<p>\u7ed3\u5408\u8fd9\u4e9b\u4fe1\u606f\u6240\u4ee5\u6211\u4eec\u5c31\u53ef\u4ee5\u8ba4\u4e3a\u5728\u8fd9\u91cc\u662f\u521b\u5efa\u51fa\u4e86\u4e00\u4e2aComponent\u51fa\u6765\u3002<\/p>\n<p>\u53e6\u5916\u503c\u5f97\u63d0\u4e00\u4e0b\u7684\u5c31\u662f\u6211\u4eec\u524d\u9762\u5df2\u7ecf\u8bb2\u8fc7Component\u4e4b\u95f4\u4e5f\u662f\u53ef\u4ee5\u6709\u4fe1\u606f\u4ea4\u4e92\u7684\uff0c\u6bd4\u5982\u6211\u4eec\u5728\u5f55\u5f71\u7684\u65f6\u5019\uff0cCameraSource\u5c31\u4f5c\u4e3a\u6570\u636e\u7684\u6765\u6e90\u88abOMXCodec\u6301\u6709\uff0c\u90a3\u4e48\u4eceOMXCodec\u8bfb\u53d6\u7684\u6570\u636e\u5b9e\u9645\u90fd\u662f\u6765\u81ea\u4e8eCameraSource\uff0c\u7136\u540e\u5c31\u88abMediaWriter\uff0c\u4f8b\u5982MPEG4Writer\u5199\u5230\u6587\u4ef6\u5f53\u4e2d\u3002<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">OMX_GetComponentVersion\r\nOMX_SendCommand\r\nOMX_GetParameter\r\nOMX_SetParameter\r\nOMX_GetConfig\r\nOMX_SetConfig\r\nOMX_GetExtensionIndex\r\nOMX_GetState\r\nOMX_UseBuffer\r\nOMX_AllocateBuffer\r\nOMX_FreeBuffer\r\nOMX_EmptyThisBuffer\r\nOMX_FillThisBuffer\r\nOMX_UseEGLImage<\/pre>\n<p>\u4ee5\u4e0a\u8fd9\u4e9b<strong>macro<\/strong>\u4f4d\u4e8eOMX_Core.h\u5f53\u4e2d\uff0c\u8fd9\u662fOpenMax\u6240\u5b9a\u4e49\u7684<br \/>\n\u9488\u5bf9\u6bcf\u4e00\u4e2aComponent\u5c01\u88c5\uff0c\u4ed6\u4eec\u8d1f\u8d23\u4e0e\u5177\u4f53\u7684codec\u8fdb\u884c\u6c9f\u901a\uff0c\u5bf9\u4e8eTI\u7684HW\uff0c\u8fd9\u4e9b\u65b9\u6cd5\u90fd\u5b9e\u73b0\u4e8eomx_proxy_common.c\u5f53\u4e2d<\/p>\n<p>\u5176\u4ed6\u5185\u5bb9\uff1a<br \/>\n1\u3001HardwareAPI.h<br \/>\nextern android::OMXPluginBase *createOMXPlugin();<br \/>\n\u5b9a\u4e49\u4e00\u4e2a\u5b9e\u4f8b\u5316plugin\u7684\u5165\u53e3\u65b9\u6cd5\uff0c\u5728OMXMaster\u5f53\u4e2d\u56de\u53bb\u52a8\u6001\u8c03\u7528\u8fd9\u4e2a\u65b9\u6cd5<\/p>\n<p>2\u3001\u5bf9\u4e8eQualcomm\u7684HW\u6765\u8bf4\uff0c\u5b83\u7684libstagefrighthw\u5b9e\u73b0\u4f4d\u4e8e\u5982\u4e0b\u4f4d\u7f6e\uff1a<br \/>\nlibomxcore.so \/path\/to\/aosp\/hardware\/qcom\/media\/mm-core\/omxcore<\/p>\n<p>3\u3001\u8fd8\u6709\u6bd4\u8f83\u5173\u952e\u7684\u5c31\u662fOpenMAX IL\u4e4b\u95f4\u672c\u8eab\u7684\u539f\u7406\uff0c\u8fd8\u6709\u76f8\u4e92\u6c9f\u901a\u662f\u600e\u4e48\u6837\u7684\uff0c\u8fd9\u4e2a\u6bd4\u8f83\u91cd\u8981\u3002<br \/>\n\u90fd\u77e5\u9053OpenMAX IL\u6700\u5927\u7684\u4f5c\u7528\u5c31\u662f\u4e00\u4e2a\u9002\u914d\u5c42\u4f5c\u7528\uff0c\u5b83\u5c01\u88c5\u4e86\u5e95\u5c42Vendor\u5bb9\u6613\u53d8\u5316\u7684\u90e8\u5206(\u4e0d\u540ccodec\/\u4e0d\u540cVendor\uff0c\u6216\u8005\u5176\u4ed6\u5f62\u5f0f\u7684\u53d8\u5316)\uff0c\u5bf9\u4e0a\u5c42\u63d0\u4f9b\u4e00\u4e2a\u7edf\u4e00\u7684\u63a5\u53e3(\u6bd4\u5982\u5728\u8fd9\u91cc\u5c31\u662fStagefright)\u3002<\/p>\n<p>\u4e00\u4e2aComponent\u7684\u72b6\u6001\u5206\u4e3a\u8fd9\u4e48\u591a\u79cd\uff0c\u8fd9\u4e9b\u5b9a\u4e49\u5728OMXCodec\u5f53\u4e2d<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">enum State {\r\n    DEAD,\r\n    LOADED,\r\n    LOADED_TO_IDLE,\r\n    IDLE_TO_EXECUTING,\r\n    EXECUTING,\r\n    EXECUTING_TO_IDLE,\r\n    IDLE_TO_LOADED,\r\n    RECONFIGURING,\r\n    ERROR\r\n};<\/pre>\n<p>Component\u4e4b\u95f4\u7684\u4ea4\u4e92\uff0c\u6bd4\u5982Tunneled communication\uff0c\u662f\u901a\u8fc7Component\u7684ComponentTunnelRequest\u65b9\u6cd5\u6765\u5b8c\u6210\u7684(TI\u7684HW\u5b9e\u73b0\u5728omx_proxy_common.c\u5f53\u4e2d)\uff0c\u4f46\u662f\u4ece\u4ee3\u7801\u4e0a\u770b\u8d77\u6765\u5728Qualcomm\u6216\u8005TI\u7684Camera\u8fd9\u5757\u90fd\u6ca1\u6709\u7528\u5230Tunneled communication\uff0cQualcomm\u6839\u672c\u5c31\u6ca1\u6709\u53bb\u5b9e\u73b0ComponentTunnelRequest\u65b9\u6cd5\u3002<\/p>\n<p>Buffer\u7684\u4f20\u8f93\u8fc7\u7a0b\uff0c\u8fd9\u5757\u521d\u770b\u5f88\u590d\u6742\uff0c\u5176\u5b9e\u6d41\u7a0b\u8fd8\u662f\u6bd4\u8f83\u6e05\u695a\u7684\u3002\u5728Camera\u5f55\u5f71\u8fd9\u4e2a\u573a\u666f\u4e2d\uff0cMediaWriter\u4f1a\u4e0d\u65ad\u7684\u8bf7\u6c42MediaSource\u7684read\u65b9\u6cd5\uff0c\u4ece\u4e2d\u95f4\u8bfb\u53d6\u6570\u636e\uff0c\u4f46\u662f\u5728MediaSource\u5185\u90e8\u4f1a\u5bf9\u5176\u8fdb\u884c\u63a7\u5236\uff0c\u7528\u7684\u5c31\u662fsignal(<strong>Condition mFrameAvailableCondition;<\/strong>)\u3002OMXCodec\u7684drainInputBuffer\/fillOutputBuffer\u8fd9\u4e24\u4e2a\u65b9\u6cd5\u6700\u91cd\u8981\uff0c\u6392\u7a7ainput\u7f13\u51b2(source\u8fc7\u6765\u7684\u6570\u636e)\u548c\u586b\u5145output\u7f13\u51b2(\u51c6\u5907\u7ed9writer\u7684\u6570\u636e)\u3002drainInputBuffer\u628a\u6570\u636e\u53d1\u5230\u5b9e\u9645\u7684codec\uff0ccodec\u6536\u5b8c\u4e4b\u540e\u53d1\u9001EMPTY_BUFFER_DONE\u6d88\u606f\u8fc7\u6765\uff0cOMXCodec\u6536\u5230\u8be5\u6d88\u606f\u7ee7\u7eed\u53d1\u9001\u6570\u636e\u5230codec\u3002\u53e6\u5916\u540c\u65f6OMXCodec\u8fd8\u4f1a\u6267\u884cfillOutputBuffer\uff0c\u5373\u5582\u7ed9codec\u4e00\u4e2a\u7a7a\u7684buffer\uff0ccodec\u7f16\u7801\u5b8c\u6210\u4e4b\u540e\u4f1a\u53d1\u9001FILL_BUFFER_DONE\u8fc7\u6765\uff0c\u8fd9\u4e2a\u6d88\u606f\u5e26\u6709\u7f16\u7801\u597d\u7684\u6570\u636e\uff0c\u5373\u88ab\u586b\u6ee1\u7684buffer\uff0c\u8fd9\u6837MediaWriter\u5c31\u6536\u5230\u7f16\u7801\u5b8c\u6210\u7684\u6570\u636e\uff0c\u7136\u540e\u4fdd\u5b58\u5c31\u53ef\u4ee5\u4e86\u3002\u7ec6\u8282\u6027\u7684\u4e1c\u897f\u5c31\u9700\u8981\u81ea\u5df1\u8ffd\u8e2a\u4ee3\u7801\u53ef\u80fd\u66f4\u597d\u7406\u89e3\uff0c\u806a\u660e\u7684\u4f60\u53ef\u80fd\u5c31\u60f3\u5230\u4e86\u90a3\u8fd9\u91cc\u662f\u4e0d\u662f\u5b58\u5728\u4e24\u4e2aBuffer\uff0c\u662f\u7684\uff0c\u4f60\u662f\u5bf9\u7684\uff0c\u8bf7\u770b<strong>List<size_t> mFilledBuffers;<\/strong>\u3002<\/p>\n<p>\u8fd9\u91cc\u518d\u7f57\u55e6\u7684\u8bb2\u89e3\u4e00\u904d\u5b9e\u9645\u8fc7\u7a0b(MPEG4\u5f55\u5f71\u4e3a\u4f8b\u5b50)\uff1a<br \/>\nMPEG4Writer\uff1a<br \/>\n\u5f00\u59cbread\u4e4b\u540e\uff0c\u4f1a\u8c03\u7528drainInputBuffers()\uff0c\u5b83\u4f1a\u4ecekPortIndexInput\u53d6\u51fa\u4e00\u7ec4buffer\u51fa\u6765\uff0c\u5148\u628a\u6570\u636e\u4eceCameraSource\u8bfb\u53d6\u5230\u8fd9\u4e2abuffer\u5f53\u4e2d\uff0c\u7136\u540e\u8c03\u7528IOMX\u7684emptyBuffer\u628abuffer\u4ea4\u7ed9\u5b9e\u9645\u7684encoder\uff0c\u7136\u540ewhile loop\u7b49\u5f85encoder\u628aoutput buffer(\u4ecekPortIndexOutput\u53d6\u51fa)\u586b\u6ee1(encoder\u7684FILL_BUFFER_DONE\u56de\u6765\u4f1a\u5c06\u901a\u8fc7msg\u5e26\u56de\u6765\u7684\u6570\u636e\u653e\u5230output buffer\uff0c\u8fd8\u4f1a\u5728mFilledBuffers\u5f53\u4e2d\u8bb0\u5f55\u4e0b\u8be5buffer\u7684index\uff0c\u5e76\u901a\u8fc7<strong>mBufferFilled.signal()<\/strong>\u5e7f\u64ad\u51fa\u6765)\uff0c\u4e5f\u5c31\u662f\u8bf4OMXCodec\u7684read\u65b9\u6cd5\u662f\u540c\u6b65\u7684\uff0c\u5fc5\u987b\u8981\u7b49\u5230\u4eceCameraSource\u8bfb\u53d6\u6570\u636e\uff0c\u7136\u540eencoder\u7f16\u7801\u5b8c\u6bd5\u8fd4\u56de\u6570\u636e\u624d\u7b97read\u7ed3\u675f\uff0c\u7136\u540e\u4f1aMPEG4Writer\u4f1a\u5c06\u8be5buffer\u62f7\u8d1d\u4e00\u4efd\u51fa\u6765\uff0c\u5e76\u4e14\u91ca\u653e\u6389\u539f\u6765\u7684buffer(\u8fd9\u4e2abuffer\u662f\u5927\u5bb6\u5171\u540c\u53ef\u4ee5\u8bbf\u95ee\u7684\uff0c\u6240\u4ee5MPEG4Writer\u4e0d\u60f3\u6216\u8005\u4e0d\u5e94\u8be5\u957f\u671f\u6301\u6709\u5b83\uff0c\u5199\u6587\u4ef6\u6240\u6d88\u8017\u7684\u65f6\u95f4\u5e76\u4e0d\u662f\u4e00\u5b9a\u7684\uff0c\u6240\u4ee5\u8fd9\u91cc\u5e94\u8be5\u7b97\u662f\u4ee5\u7a7a\u95f4\u6362\u65f6\u95f4\u7684\u4e00\u79cd\u505a\u6cd5)\u3002<\/p>\n<p>buffer\u7684\u5206\u914d\uff1a<br \/>\ninput buffer\u7684MediaBuffer\u662f\u5728CameraSource\u5f53\u4e2d\u5206\u914d\uff0cOMXCodec\u5f53\u4e2drelease(EMPTY_BUFFER_DONE\u56de\u6765\u5982\u679cbuffer\u6ca1\u6709\u88abrelease\u6389\u5c31\u6267\u884crelease\u8fc7\u7a0b)<br \/>\noutput buffer\u7684MediaBuffer\u5206\u591a\u79cd\u60c5\u51b5\uff0c\u6709\u53ef\u80fd\u662f\u5728allocateBuffer\u7684\u65f6\u5019\u5206\u914d\u7684\uff0c\u6709\u53ef\u80fd\u662fFILL_BUFFER_DONE\u56de\u6765\u7684\u65f6\u5019\u5206\u914d\uff0c\u5728MediaWriter\u8bfb\u53d6\u5230\u5904\u7406\u597d\u4e4b\u540e\u7684\u6570\u636e\u81ea\u5df1\u62f7\u8d1d\u8be5\u6570\u636e\u4e00\u4efd\u4e4b\u540erelease\u3002<\/p>\n<p>End Of Stream\uff1a<br \/>\n\u4e00\u822c\u60c5\u51b5decoder\u6216encoder\u544a\u8bc9\u6211\u4eecEOS\uff0c\u4f46\u662f\u6709\u4e9b\u65f6\u5019\u4e0d\u544a\u8bc9\u6211\u4eec\u7684\u65f6\u5019OMXCodec\u4e5f\u6709\u505aworkaround\uff0c\u901a\u8fc7\u8ba1\u7b97\u4e0d\u5728OMX Component\u7684buffer\u7684\u4e2a\u6570\uff0c\u5982\u679c\u6240\u6709buffer\u90fd\u4e0d\u88abOMX Component\u6240\u6301\u6709\uff0c\u5c31\u8ba4\u4e3a\u5df2\u7ecf\u5230EOS\u4e86\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Stagefright\u548ccodec\u7684\u4ea4\u4e92\u662f\u901a\u8fc7OpenMAX IL\u6765\u5b8c\u6210\u7684\u3002 OpenMAX IL\u7684\u89c4\u8303\u5934\u6587\u4ef6\u4f4d\u4e8e \/path\/to\/aosp\/frameworks\/native\/include\/media\/openmax \u6982\u8ff0\u4e0bOpenMAX IL\uff0c\u5b83\u5305\u62ec\u5ba2\u6237\u7aef(Client)\uff0c\u7ec4\u4ef6(Component)\uff0c\u7aef\u53e3(Port)\uff0c\u96a7\u9053\u5316(Tunneled)\u3002 Client\u662f\u8c03\u7528Component\u7684\u5bf9\u8c61\uff0cPort\u548cTunneled\u662fComponent\u4e4b\u95f4\u901a\u4fe1\u7684\u65b9\u5f0f\uff0cComponent\u4e4b\u95f4\u8fd8\u53ef\u4ee5\u5b58\u5728\u79c1\u6709\u7684\u901a\u4fe1\u65b9\u5f0f\u3002 \u7ec4\u4ef6(Component)\u7684\u529f\u80fd\u548c\u5176\u5b9a\u4e49\u7684\u7aef\u53e3\u7c7b\u578b\u5bc6\u5207\u76f8\u5173\uff0c\u901a\u5e38\u60c5\u51b5\u4e0b\uff1a\u53ea\u6709\u4e00\u4e2a\u8f93\u51fa\u7aef\u53e3\u7684\uff0c\u4e3aSource\u7ec4\u4ef6\uff1b\u53ea\u6709\u4e00\u4e2a\u8f93\u5165\u7aef\u53e3\u7684\uff0c\u4e3aSink\u7ec4\u4ef6\uff1b\u6709\u591a\u4e2a\u8f93\u5165\u7aef\u53e3\uff0c\u4e00\u4e2a\u8f93\u51fa\u7aef\u53e3\u7684\u4e3aMux\u7ec4\u4ef6\uff1b\u6709\u4e00\u4e2a\u8f93\u5165\u7aef\u53e3\uff0c\u591a\u4e2a\u8f93\u51fa\u7aef\u53e3\u7684\u4e3aDeMux\u7ec4\u4ef6\uff1b\u8f93\u5165\u8f93\u51fa\u7aef\u53e3\u5404\u4e00\u4e2a\u7ec4\u4ef6\u7684\u4e3a\u4e2d\u95f4\u5904\u7406\u73af\u8282\uff0c\u8fd9\u662f\u6700\u5e38\u89c1\u7684\u7ec4\u4ef6\u3002 \u5728Android 2.2\u4ee5\u53ca\u4e4b\u540e\uff0cStagefright\u662f\u4f5c\u4e3aOpenMAX IL\u7684\u4e0a\u5c42\u5b58\u5728\u7684\uff0c\u5b83\u8ddfOpenMAX IL\u5bf9\u63a5\uff0c\u7136\u540eOpenMAX IL\u53c8\u5c01\u88c5\u4e86\u5177\u4f53\u7684codec\u3002 \u4e4b\u524d\u6211\u6709\u5728http:\/\/guoh.ai\/lifelog\/2013\/06\/android-mediarecorder-architecture\/\u5206\u6790\u8fc7StagefrightRecorder\uff0c\u5f53\u65f6\u8ddfcodec\u7684\u96c6\u6210\u6211\u6ca1\u6709\u4ed4\u7ec6\u5206\u6790\u3002 \u8fd9\u7bc7\u6587\u7ae0\u4f1a\u8be6\u7ec6\u5206\u6790\u4e0b\u8fd9\u4e2a\u903b\u8f91\u8fc7\u7a0b\u3002 \u9996\u5148\u6211\u4eec\u4f1a\u78b0\u5230\u51e0\u4e2a\u5173\u952e\u7684\u7c7b\uff0c\u7b2c\u4e00\u4e2a\u5c31\u662fOMX\uff0c\u5e76\u4e14\u5b83\u7684\u6784\u9020\u65b9\u6cd5\u5f53\u4e2d\u4f1a\u53bb\u521b\u5efa\u4e00\u4e2aOMXMaster\uff0c\u7ee7\u7eed\u8ffd\u8e2a\u4e0b\uff0c\u53d1\u73b0OMXMaster\u6b63\u5982\u5176\u540d\u5b57\u6240\u793a\uff0c\u662f\u4e00\u4e2a\u7ba1\u7406\u8005\u89d2\u8272\u3002 OMXMaster\u4f5c\u4e3a\u7ba1\u7406\u8005\uff0c\u6bcf\u6dfb\u52a0\u4e00\u4e2aplugin\u8fdb\u6765\uff0c\u90fd\u4f1a\u8bb0\u5f55\u5728 KeyedVector&lt;String8, OMXPluginBase *&gt; mPluginByComponentName; \/\/ \u91cd\u590d\u540d\u5b57\u7684codec\u4e0d\u4f1a\u518d\u8ba9\u5176\u52a0\u8fdb\u6765\uff0c\u4e5f\u5c31\u662f\u5b83\u4f1a\u53bb\u786e\u5b9a\u8be5plugin\u652f\u6301\u591a\u5c11codec\uff0c\u7136\u540e\u8bb0\u5f55\u4e0b\u6765 List&lt;OMXPluginBase *&gt; mPlugins; \/\/ \u4e3b\u8981\u8d1f\u8d23\u91ca\u653e\u5185\u5b58(\u4e0d\u4e0e\u4e1a\u52a1\u76f8\u5173\uff0c\u53ea\u7ba1\u6709\u6dfb\u52a0\u8fdb\u6765\u7684plugin) OMXMaster\u5230\u5e95\u4f1a\u52a0\u591a\u5c11\u4e2aOMXPlugin\u8fdb\u6765\uff1f \u4ee5\u53ca\u5230\u5e95\u4f1a\u6709\u591a\u5c11\u4e2aOMXMaster\uff1f \u6709\u591a\u5c11\u4e2aOMX\u5c31\u6709\u591a\u5c11\u4e2aOMXMaster\uff0c\u90a3\u6709\u591a\u5c11\u4e2aOMX\u5462\uff1f \u53ea\u6709\u4e00\u4e2a\uff0c\u53c2\u89c1 sp&lt;IOMX&gt; MediaPlayerService::getOMX() { Mutex::Autolock autoLock(mLock); if (mOMX.get() == NULL) { mOMX = new OMX; } return mOMX; } \u90a3\u4f1a\u6709\u591a\u5c11\u4e2aOMXPlugin\u5462\uff1f\u3002 \u4e00\u4e2aSoftOMXPlugin\uff0c\u5f53\u4e2d\u53ef\u4ee5\u52a0\u8f7d\u5f88\u591acodec(s)\u8fdb\u6765 \/path\/to\/aosp\/frameworks\/av\/media\/libstagefright\/codecs\/ \u6709\u591a\u5c11soft &hellip; <a href=\"https:\/\/guoh.ai\/lifelog\/2013\/06\/interaction-between-stagefright-and-codec\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Stagefright\u548ccodec\u7684\u4ea4\u4e92<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_gfmr_meta_descriptions":[],"_gfmr_multilingual_taxonomy_terms":[],"footnotes":""},"categories":[7,28,34],"tags":[],"class_list":["post-617","post","type-post","status-publish","format-standard","hentry","category-android","category-cpp","category-multimedia"],"_links":{"self":[{"href":"https:\/\/guoh.ai\/lifelog\/wp-json\/wp\/v2\/posts\/617","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/guoh.ai\/lifelog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/guoh.ai\/lifelog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/guoh.ai\/lifelog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/guoh.ai\/lifelog\/wp-json\/wp\/v2\/comments?post=617"}],"version-history":[{"count":17,"href":"https:\/\/guoh.ai\/lifelog\/wp-json\/wp\/v2\/posts\/617\/revisions"}],"predecessor-version":[{"id":675,"href":"https:\/\/guoh.ai\/lifelog\/wp-json\/wp\/v2\/posts\/617\/revisions\/675"}],"wp:attachment":[{"href":"https:\/\/guoh.ai\/lifelog\/wp-json\/wp\/v2\/media?parent=617"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/guoh.ai\/lifelog\/wp-json\/wp\/v2\/categories?post=617"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/guoh.ai\/lifelog\/wp-json\/wp\/v2\/tags?post=617"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}