<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>逆流的鱼yuiop</title>
  
  
  <link href="https://www.stockclaw.asia/atom.xml" rel="self"/>
  
  <link href="https://www.stockclaw.asia/"/>
  <updated>2026-05-11T10:09:03.567Z</updated>
  <id>https://www.stockclaw.asia/</id>
  
  <author>
    <name>逆流的鱼yuiop</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>AI 编程工具大家实际使用中哪个综合下来最好用？</title>
    <link href="https://www.stockclaw.asia/2026/05/11/AI-%E7%BC%96%E7%A8%8B%E5%B7%A5%E5%85%B7%E5%A4%A7%E5%AE%B6%E5%AE%9E%E9%99%85%E4%BD%BF%E7%94%A8%E4%B8%AD%E5%93%AA%E4%B8%AA%E7%BB%BC%E5%90%88%E4%B8%8B%E6%9D%A5%E6%9C%80%E5%A5%BD%E7%94%A8%EF%BC%9F/"/>
    <id>https://www.stockclaw.asia/2026/05/11/AI-%E7%BC%96%E7%A8%8B%E5%B7%A5%E5%85%B7%E5%A4%A7%E5%AE%B6%E5%AE%9E%E9%99%85%E4%BD%BF%E7%94%A8%E4%B8%AD%E5%93%AA%E4%B8%AA%E7%BB%BC%E5%90%88%E4%B8%8B%E6%9D%A5%E6%9C%80%E5%A5%BD%E7%94%A8%EF%BC%9F/</id>
    <published>2026-05-11T10:06:40.000Z</published>
    <updated>2026-05-11T10:09:03.567Z</updated>
    
    <content type="html"><![CDATA[<p>Codex, Cursor, Claude Code</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Codex, Cursor, Claude Code&lt;/p&gt;
</summary>
      
    
    
    
    
  </entry>
  
  <entry>
    <title>《Android音视频开发》勘误</title>
    <link href="https://www.stockclaw.asia/2019/06/09/Android%E9%9F%B3%E8%A7%86%E9%A2%91%E5%BC%80%E5%8F%91%E5%8B%98%E8%AF%AF/"/>
    <id>https://www.stockclaw.asia/2019/06/09/Android%E9%9F%B3%E8%A7%86%E9%A2%91%E5%BC%80%E5%8F%91%E5%8B%98%E8%AF%AF/</id>
    <published>2019-06-09T02:50:07.000Z</published>
    <updated>2019-06-09T03:05:56.000Z</updated>
    
    <content type="html"><![CDATA[<center><br><img src="/upload/fengmian.png" alt="这里写图片描述"><br></center><p>经历了两年多，我的著作终于和大家见面了，写书是一件很磨练人耐力的事情<span id="more"></span> ，从打算写一本书开始后，心里无时不刻有一块大石头压在头顶。一来要保证专业性，二来要保证质量，同时还要兼具备怎么表达，才能让别人明白所说的意思。所以看起来没有那么简单。<strong>近年来，直播，短视频行业相关业务发展迅猛。Android音视频开发门槛相对高些，很多有特色或者核心模块基本都是NDK开发</strong>，<strong>而NDK开发很多实际上都是C/C++写的Code,那么同时也要学习C/C++，而Android应用开发，很多时候用Java就能开发大部分应用</strong>。所以音视频有特色都是C/C++开发。这让很多不少做Java开发的朋友望而却步了。但音视频更多是和产品结合起来，所以肯定有很多业务需求是上层来配合做的。不然光写逻辑，没有数据或其他UI展示，这样的产品也是不好玩的。但是如果在做应用层又了解一些音视频相关逻辑，那么配合起来就会事半功倍了。之前很多同学和我反馈要是能写一本书这么详细介绍内容就好了。其实我一直在写，只是没有写好的那一天还不想通知大家，不过现在好了。我的著作：《Android音视频开发》一书终于能和大家见面了。也欢迎大家购买。先到先得，首次印刷数量有限，希望这个封面大家喜欢：</p><p><img src="/upload/android_book.png" alt="这里写图片描述"></p><p>下面就来和大家简单说一下本书内容吧，本书主要分为11大篇章，每章要学的东西不少：</p><ul><li><p>第一章：介绍了常用音视频术语，了解一些音视频的基础概念，对音视频一些理论进行分类，让读者更好的系统有条理掌握这些基础概念。</p></li><li><p>第二章：介绍了Android应用层使用的系统播放器-MediaPlayer，从上到下的源码分析与介绍，通过某个点，向下深入。</p></li><li><p>第三章：介绍了Android多媒体管理调度的服务者- MediaPlayerService，以及如何为多媒体播放提供服务。</p></li><li><p>第四章：介绍了Android系统中的StagefrightPlayer，在Android 系统5.1 版本之前，这个扮演了重要的角色。有必要对它进行了解</p></li><li><p>第五章：介绍了Android系统中的NuPlayer-流媒体播放的新生力量，在Android 系统5.1 版本之后（包含5.1版本），NuPlayer基于StagefrightPlayer的基础类构建，利用了更底层的ALooper/AHandler机制来异步解码播放。</p></li><li><p>第六章：介绍了OpenMAX （OMX）框架相关，OpenMAX是一个多媒体应用程序的标准，涉及OpenMAX IL API 能够在Android应用程序、多媒体框架和编解码库，以及其支持的组件（比如，sources 和 sinks）之间建立统一的接口。</p></li><li><p>第七章：介绍了FFmpeg库在Windows，mac OS，以及Linux下编译并移植。同时介绍了FFmpeg常用的命令进行处理音视频。</p></li><li><p>第八章：介绍了FFmpeg源码分析及实战开发案例，对做音视频开发，会使用FFmpeg库，以及了解源码是基本功。通过案例来感受FFmpeg库的魅力。</p></li><li><p>第九章：介绍了直播开发的技术，主要涉及直播原理、采集数据、编码、推流、播放等。同时写了一个Android推流器案例，来实现一个简单直播app。也介绍了直播过程中一些优化点，帮助提升直播体验。</p></li><li><p>第十章：介绍了H.264码流结构及H.265码流结构，在音视频开发中，可以分析数据有无特殊性问题及异常问题排查。帮助定位修复问题</p></li><li><p>第十一章：介绍了常见的视频封装格式，以及对封装格式原理和内部结构进行分析。可以学习到音视频数据是怎么一步一步组配的。</p></li></ul><h3 id="源码"><a href="#源码" class="headerlink" title="源码"></a>源码</h3><p>链接:<a href="https://pan.baidu.com/s/16OUkZToVQYhkrrxFszi0Jg">https://pan.baidu.com/s/16OUkZToVQYhkrrxFszi0Jg</a>  密码:mzas</p><h3 id="码流分析工具"><a href="#码流分析工具" class="headerlink" title="码流分析工具"></a>码流分析工具</h3><p>链接：<a href="https://pan.baidu.com/s/1iUksNQ8MW3JHw258cb3Yzw">https://pan.baidu.com/s/1iUksNQ8MW3JHw258cb3Yzw</a>  密码：e08o </p><h3 id="勘误列表"><a href="#勘误列表" class="headerlink" title="勘误列表"></a>勘误列表</h3><ul><li><p>1、Page-3，Line-8，错误类型–错别字，AudioTrack 写成 “AudiTrack”;</p></li><li><p>2、Page-6，错误类型–描述错误，关于PCM的采样率和比特率换算，常见的比特率并没有44.1Hz，而是44.1KHz，即使是44.1Hz，16位的精度，换算的比特率也不是4410016kb/s的结果;</p></li><li><p>3、第一章中关于YUV的概念介绍中说 :“YUV：也被称作YCrCb”, 应为“YCbCr”, 在YUV家族中，YCbCr是在计算机系统中应用最多的成员，其应用领域很广泛，JPEG、MPEG均采用此格式。一般人们所讲的YUV大多是指YCbCr。引用微软对YV12和NV12的描述：<a href="https://docs.microsoft.com/en-us/previous-versions/aa904813(v=vs.80)">https://docs.microsoft.com/en-us/previous-versions/aa904813(v=vs.80)</a></p></li></ul><p>YV12<br>　　All of the Y samples appear first in memory as an array of unsigned char values. This array is followed immediately by all of the V (Cr) samples. The stride of the V plane is half the stride of the Y plane, and the V plane contains half as many lines as the Y plane. The V plane is followed immediately by all of the U (Cb) samples, with the same stride and number of lines as the V plane (Figure 12).</p><p>NV12<br>　　All of the Y samples are found first in memory as an array of unsigned char values with an even number of lines. The Y plane is followed immediately by an array of unsigned char values that contains packed U (Cb) and V (Cr) samples, as shown in Figure 13. When the combined U-V array is addressed as an array of little-endian WORD values, the LSBs contain the U values, and the MSBs contain the V values. NV12 is the preferred 4:2:0 pixel format for DirectX VA. It is expected to be an intermediate-term requirement for DirectX VA accelerators supporting 4:2:0 video.</p><p>可以发现 U (Cb) ，V (Cr)，那YUV就是YCbCr.</p><ul><li><p>4、Page-23处libmedia.so库源文件的目录不是frameworks/base/media/libmedia，而是在frameworks/av/media/libmedia</p></li><li><p>5、Page-15，得到软引用对象，应为“得到弱引用对象”</p></li><li><p>6、Page-210 metadata，应为“元数据”</p></li><li><p>7、Page-212 priv_data_size，应为“某种格式文件的数据大小”</p></li><li><p>8、Page-198 第一个命令写成前面一节降噪命令了，争取画中画命令应为“ffmpeg -i input1 -i input2 -filter_complex overlay=x:y output”</p></li><li><p>9、Page-46 首先找到入口，在frameworks/base/media/mediaserver/main_mediaserver.cpp中，应为“首先找到入口，在frameworks/av/media/mediaserver/main_mediaserver.cpp中”</p></li><li><p>10、Page-47 接下来看看interface_cast是什么，其处于frameworks/base/include/binder/IInterface.h中，应为“接下来看看interface_cast是什么，其处于frameworks/native/include/binder/IInterface.h中”</p></li><li><p>11、Page-48 其处于frameworks/base/include/binder/IServiceManager.h中，应为“接下来看看interface_cast是什么，其处于frameworks/native/include/binder/IServiceManager.h中”</p></li><li><p>12、Page-49 开始添加服务内部，在frameworks/base/media/libmediaplayerservice/MediaPlayerService.cpp中，应为“开始添加服务内部，在frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp中”</p></li><li><p>13、Page-52 其处于frameworks/base/libs/binder/IserviceManager.cpp中，应为“ 其处于frameworks/native/libs/binder/IServiceManager.cpp中”</p></li><li><p>14、Page-53 继续在BpBinder中寻找实现代码，其处于frameworks/base/libs/binder/BpBinder.cpp中，应为“继续在BpBinder中寻找实现代码，其处于frameworks/native/libs/binder/BpBinder.cpp中”</p></li></ul><h2 id="License"><a href="#License" class="headerlink" title="License"></a>License</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">Copyright (C) &lt;2018&gt;  &lt;hejunlin&gt;</span><br><span class="line"></span><br><span class="line">This program is free software: you can redistribute it and/or modify</span><br><span class="line">it under the terms of the GNU General Public License as published by</span><br><span class="line">the Free Software Foundation, either version 3 of the License, or</span><br><span class="line">(at your option) any later version.</span><br><span class="line"></span><br><span class="line">This program is distributed in the hope that it will be useful,</span><br><span class="line">but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span class="line">MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span class="line">GNU General Public License for more details.</span><br><span class="line"></span><br><span class="line">You should have received a copy of the GNU General Public License</span><br><span class="line">along with this program.  If not, see &lt;https://www.gnu.org/licenses/&gt;.</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;/upload/fengmian.png&quot; alt=&quot;这里写图片描述&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;经历了两年多，我的著作终于和大家见面了，写书是一件很磨练人耐力的事情</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>为什么有的大公司代码也很烂？</title>
    <link href="https://www.stockclaw.asia/2019/03/31/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%9C%89%E7%9A%84%E5%A4%A7%E5%85%AC%E5%8F%B8%E4%BB%A3%E7%A0%81%E4%B9%9F%E5%BE%88%E7%83%82%EF%BC%9F/"/>
    <id>https://www.stockclaw.asia/2019/03/31/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%9C%89%E7%9A%84%E5%A4%A7%E5%85%AC%E5%8F%B8%E4%BB%A3%E7%A0%81%E4%B9%9F%E5%BE%88%E7%83%82%EF%BC%9F/</id>
    <published>2019-03-31T13:53:55.000Z</published>
    <updated>2019-03-31T13:57:52.000Z</updated>
    
    <content type="html"><![CDATA[<center><br><img src="/upload/shirenzu.jpg" alt="这里写图片描述"><br></center><p>最近一个朋友进入梦寐以求的大公司，和我抱怨了下，他们大公司代码写的也不怎么好<span id="more"></span> ，连他一个菜鸡都能看出逻辑漏洞，都没人改。让他有点怀疑人生了。那么为什么有的大公司代码也会如此烂呢？</p><p>很多人第一个给的原因就是：<strong>历史原因</strong>。可能这是最重要的点，如果是老项目，几乎每个人都是一来接手一个项目，如果之前维护这个项目的人，水平比较高，代码行云流水，代码规范，逻辑严谨度都很高，恭喜你，你获取一个学习优秀代码的成长起点。对于你是幸运的，鱼哥之前接触过这样的项目，真是写的好，巧妙的设计模式，逻辑清晰，和读系统源码一样。但是你没那么幸运，接手一个水平不是很高的团队维护的代码，那你就有事情做了，重新写，还是重构。烂代码跟一坨屎一样，很多时候就是和一坨屎共处千万别深挖，说不定把哪里挖塌了把你埋了，扔一坨代码到屎山上，达到自己目的，能跑就行了，你还要搞清楚山上的屎哪一坨是谁拉的，拉的人吃了什么，就没什么意思了。能在超级大的屎山上扔一坨代码进去，把自己的事干了，也是本事真的，毕竟谁没维护过烂代码。复杂度足够大，都会成为屎山的，什么设计模式都没什么鸟用。这时候可以花时间加班来重写吧，不然你干不下去的，等着你的要么走人。</p><p>大公司业务逻辑复杂这点很容易理解，一个系统和N多系统集成，一个业务对象上百个字段和几十种状态，一个流程几十个环节。大公司人员变动大很多开发的还是外包人员，外包人员的流动性可想而知。技术更新换代代价太大。但没有人敢去推倒重来，单单修改后的测试工作量就不可小觑。而且改好了无功（不出绩效），改出问题了谁都负责不起，所以只要代码能工作，后面的开发都是在上面修修补补，导致整体代码千疮百孔惨不忍睹。技术leader只关注功能，不关注代码很多leader其实根本不是写代码写上去的，而是直接就去做了“架构师”，说实话他自己都写不好代码，这也是很主要的一个原因。</p><p>还有，领导也不会关心你什么技术实现，不会关心你是10行代码还是1000行代码。所以，这种背景下，要把代码写得好到好像一个人写的一样人能看懂，还是很难的。老代码只要没有毛病，没人会去优化装饰，没有人会去干这些吃力不讨好的工作，代码重构/代码评审很多时候是流于形式，只是说说而已。有些大项目每年的代码量以50%速度增加，真是好大的负资产啊！</p><p>那有人说，大公司不是每个人技术都很强的么？有这个想法的人，你就大错特错了，大公司每年都会校招很多应届生，有些应届生在短短几年后成才起来，跑路了，有些没有成长起来的，还是要持续写代码，那么自然就有隐患了，如果不是很精干的工程师来负责review代码的话。就会变成一个一坨屎坑。面试时，招大牛是需要价钱的，很多公司由于成本原因，并不会这么去做。</p><p>一个团队，在任何时候，都应该分辨得出：<br>分辨什么样的烂是真烂，什么样的烂是业务复杂；<br>分辨不出，就不要去修改。</p><p>也应该积极寻求：如果是业务复杂，能不能更简化更抽象一些；如果是烂，能不能在有限的成本中改好一些。</p>]]></content>
    
    
    <summary type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;/upload/shirenzu.jpg&quot; alt=&quot;这里写图片描述&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;最近一个朋友进入梦寐以求的大公司，和我抱怨了下，他们大公司代码写的也不怎么好</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>视频画中画效果，拖动进度条可以seek到相应视频帧显示</title>
    <link href="https://www.stockclaw.asia/2019/03/31/%E8%A7%86%E9%A2%91%E7%94%BB%E4%B8%AD%E7%94%BB%E6%95%88%E6%9E%9C%EF%BC%8C%E6%8B%96%E5%8A%A8%E8%BF%9B%E5%BA%A6%E6%9D%A1%E5%8F%AF%E4%BB%A5seek%E5%88%B0%E7%9B%B8%E5%BA%94%E8%A7%86%E9%A2%91%E5%B8%A7%E6%98%BE%E7%A4%BA/"/>
    <id>https://www.stockclaw.asia/2019/03/31/%E8%A7%86%E9%A2%91%E7%94%BB%E4%B8%AD%E7%94%BB%E6%95%88%E6%9E%9C%EF%BC%8C%E6%8B%96%E5%8A%A8%E8%BF%9B%E5%BA%A6%E6%9D%A1%E5%8F%AF%E4%BB%A5seek%E5%88%B0%E7%9B%B8%E5%BA%94%E8%A7%86%E9%A2%91%E5%B8%A7%E6%98%BE%E7%A4%BA/</id>
    <published>2019-03-31T13:11:11.000Z</published>
    <updated>2019-03-31T14:11:52.000Z</updated>
    
    <content type="html"><![CDATA[<center><br><img src="/upload/guiqi.jpg" alt="这里写图片描述"><br></center><p>在视频开发中，我们常常看到这样的效果，拖动进度条时，或是在进度条上方或是在屏幕中间，显示拖动进度条位置时刻的某一帧画面。<br><span id="more"></span><br><img src="https://user-gold-cdn.xitu.io/2018/11/10/166fdf6653b8fbb5?w=1080&amp;h=608&amp;f=webp&amp;s=27740" alt=""></p><p>这个需求，如果是你，你会如何做？</p><p>通常一个需求，不仅要考虑实现，还有考虑一些是否有性能上影响。</p><p>下面我想到的4个方案：</p><p>1、在拖动过程中，可以通过TextureView来显示预览图，拖动进度条到某个position后，通过textureView.getBitmap()拿到对应的截图，用于展示。</p><p>2、通过MediaMetadataRetriever 只能获取你指定时间的附近的关键帧（Key frame）<br>MediaMetadataRetriever mmr = new MediaMetadataRetriever();<br>mmr.setDataSource(renderOutputFilePath);<br>mmr.getFrameAtTime(1x1000x1000,OPTION_CLOSEST_SYNC );//获取1秒附近的关键帧，注意，只是附近，获取不到精确位置的图片。但是用于预览也够了</p><p>3、通过GLSurfaceView，拖到到某个事件点后，来onDrawFrame，这种方式比较高效。</p><p>4、FFmpeg实现，获取某个位置的picture，github上有封装好的实现此功能的库，类似和MediaMetadataRetriever一样的用法，可以更精准，高效。<br>链接：<a href="https://github.com/wseemann/FFmpegMediaMetadataRetriever，">https://github.com/wseemann/FFmpegMediaMetadataRetriever，</a><br>原理就是取某个timebase的关键帧。然后回调出去展示。</p><p>需要注意的是，取帧是个耗时的操作，需要放到子线程中<br><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();</span><br><span class="line">mmr.setDataSource(mUri);</span><br><span class="line"></span><br><span class="line">//获取第一帧原尺寸图片</span><br><span class="line">mmrc.getFrameAtTime();</span><br><span class="line"></span><br><span class="line">//获取指定位置的原尺寸图片 注意这里传的timeUs是微秒</span><br><span class="line">mmrc.getFrameAtTime(timeUs, option);</span><br><span class="line"></span><br><span class="line">//获取指定位置指定宽高的缩略图</span><br><span class="line">mmrc.getScaledFrameAtTime(timeUs, MediaMetadataRetrieverCompat.OPTION_CLOSEST, width, height);</span><br><span class="line"></span><br><span class="line">//获取指定位置指定宽高并且旋转的缩略图</span><br><span class="line">mmrc.getScaledFrameAtTime(timeUs, MediaMetadataRetrieverCompat.OPTION_CLOSEST, width, height, rotate);</span><br></pre></td></tr></table></figure></p><p>Demo效果图：<br><img src="https://user-gold-cdn.xitu.io/2018/11/10/166fe058c9ce51dd?w=210&amp;h=383&amp;f=gif&amp;s=109257" alt=""></p><p>推荐书籍（亚马逊、京东、天猫、当当均有售）：</p><p><img src="https://upload-images.jianshu.io/upload_images/424500-4d9cea92c3fc51ea.png?imageMogr2/auto-orient/" alt="image.png"></p><blockquote><p>内容简介：近年来，直播、短视频行业的相关业务发展迅猛，本书主要介绍其中涉及的Android音视频开发相关技术。本书一共有11章，分别介绍了音视频基础知识、MediaPlayer、MediaPlayerService、StagefrightPlayer、NuPlayer、OpenMAX框架、FFmpeg项目、FFmpeg源码分析及实战、直播技术、H.264编码及H.265编码、视频格式分析内容。希望本书能帮助读者系统学习、化繁为简，在Android音视频开发的道路上不断进步。</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;/upload/guiqi.jpg&quot; alt=&quot;这里写图片描述&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;在视频开发中，我们常常看到这样的效果，拖动进度条时，或是在进度条上方或是在屏幕中间，显示拖动进度条位置时刻的某一帧画面。&lt;br&gt;</summary>
    
    
    
    <category term="画中画" scheme="https://www.stockclaw.asia/categories/%E7%94%BB%E4%B8%AD%E7%94%BB/"/>
    
    
    <category term="FFmpeg" scheme="https://www.stockclaw.asia/tags/FFmpeg/"/>
    
  </entry>
  
  <entry>
    <title>ijkplayer如何使用FFmpeg 4.0内核？</title>
    <link href="https://www.stockclaw.asia/2019/03/31/ijkplayer%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8FFmpeg-4-0%E5%86%85%E6%A0%B8%EF%BC%9F/"/>
    <id>https://www.stockclaw.asia/2019/03/31/ijkplayer%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8FFmpeg-4-0%E5%86%85%E6%A0%B8%EF%BC%9F/</id>
    <published>2019-03-31T13:02:54.000Z</published>
    <updated>2019-03-31T13:58:48.000Z</updated>
    
    <content type="html"><![CDATA[<center><br><img src="/upload/wushuang.jpeg" alt="这里写图片描述"><br></center><p>相信不少使用ijkplayer的朋友，都在埋怨，很多issue没有人去解，master上分支已经停留在201801月，<span id="more"></span> 这现在一年都快过去了，官方不维护了么？其实，人家一直在维护和更新。只不过ijkplayer是基于FFmpeg作为内核。上层ijkplayer封装的东西，改动性没有那么大，出问题，也都是在底层FFmpeg改。如Demux，Codec等，还有各种协议。</p><p>所以，我告诉大家如何用ijkplayer内核最新稳定版本。我们一定对它的工程结构了解，他们是怎么把FFmpeg，libyuv，soundtouch，等第三方库作为contrib的。<br><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">IJK_FFMPEG_UPSTREAM=https://github.com/Bilibili/FFmpeg.git</span><br><span class="line">IJK_FFMPEG_FORK=https://github.com/Bilibili/FFmpeg.git</span><br><span class="line">IJK_FFMPEG_COMMIT=ff3.4--ijk0.8.7--20180103--001</span><br><span class="line">IJK_FFMPEG_LOCAL_REPO=extra/ffmpeg</span><br><span class="line"></span><br><span class="line">set -e</span><br><span class="line">TOOLS=tools</span><br><span class="line"></span><br><span class="line">git --version</span><br><span class="line"></span><br><span class="line">echo &quot;== pull ffmpeg base ==&quot;</span><br><span class="line">sh $TOOLS/pull-repo-base.sh $IJK_FFMPEG_UPSTREAM $IJK_FFMPEG_LOCAL_REPO</span><br><span class="line"></span><br><span class="line">function pull_fork()</span><br><span class="line">&#123;</span><br><span class="line">    echo &quot;== pull ffmpeg fork $1 ==&quot;</span><br><span class="line">    sh $TOOLS/pull-repo-ref.sh $IJK_FFMPEG_FORK android/contrib/ffmpeg-$1 $&#123;IJK_FFMPEG_LOCAL_REPO&#125;</span><br><span class="line">    cd android/contrib/ffmpeg-$1</span><br><span class="line">    git checkout $&#123;IJK_FFMPEG_COMMIT&#125; -B ijkplayer</span><br><span class="line">    cd -</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>这里master上依赖的库是<code>ff3.4--ijk0.8.7--20180103--001</code>,是基于FFmpeg3.4的，新版本FFmpeg的都是4.1了，同时修复了很多问题和一些新的Feature。</p><p>ijkplayer的维护者，也是一直在勤快的更新。</p><p>所以要改动，只需要把IJK_FFMPEG_COMMIT=ff3.4–ijk0.8.7–20180103–001换成JK_FFMPEG_COMMIT=ff4.0–ijk0.8.25–20181123–001就可以，然后再做验证性测试。</p><p>对于iOS也是，在init-ios.sh中<br><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">IJK_FFMPEG_UPSTREAM=https://github.com/Bilibili/FFmpeg.git</span><br><span class="line">IJK_FFMPEG_FORK=https://github.com/Bilibili/FFmpeg.git</span><br><span class="line">IJK_FFMPEG_COMMIT=ff3.4--ijk0.8.7--20180103--001</span><br><span class="line">IJK_FFMPEG_LOCAL_REPO=extra/ffmpeg</span><br><span class="line"></span><br><span class="line">IJK_GASP_UPSTREAM=https://github.com/Bilibili/gas-preprocessor.git</span><br><span class="line"></span><br><span class="line"># gas-preprocessor backup</span><br><span class="line"># https://github.com/Bilibili/gas-preprocessor.git</span><br><span class="line"></span><br><span class="line">if [ &quot;$IJK_FFMPEG_REPO_URL&quot; != &quot;&quot; ]; then</span><br><span class="line">    IJK_FFMPEG_UPSTREAM=$IJK_FFMPEG_REPO_URL</span><br><span class="line">    IJK_FFMPEG_FORK=$IJK_FFMPEG_REPO_URL</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">if [ &quot;$IJK_GASP_REPO_URL&quot; != &quot;&quot; ]; then</span><br><span class="line">    IJK_GASP_UPSTREAM=$IJK_GASP_REPO_URL</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">set -e</span><br><span class="line">TOOLS=tools</span><br></pre></td></tr></table></figure><br>也是改法和上面相同。其他第三方库libyuv，soundtouch，修改对应脚本就行。需要注意的是，编译时，如果有一些新旧接口变化，可以用对比工具对比下。升级的好处，可以规避很多问题。大家有兴趣可以试试。</p>]]></content>
    
    
    <summary type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;/upload/wushuang.jpeg&quot; alt=&quot;这里写图片描述&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;相信不少使用ijkplayer的朋友，都在埋怨，很多issue没有人去解，master上分支已经停留在201801月，</summary>
    
    
    
    <category term="ijkplayer" scheme="https://www.stockclaw.asia/categories/ijkplayer/"/>
    
    
    <category term="FFmpeg" scheme="https://www.stockclaw.asia/tags/FFmpeg/"/>
    
  </entry>
  
  <entry>
    <title>H.264标准（三）F4V封装格式详解</title>
    <link href="https://www.stockclaw.asia/2017/07/02/H-264%E6%A0%87%E5%87%86%EF%BC%88%E4%B8%89%EF%BC%89F4V%E5%B0%81%E8%A3%85%E6%A0%BC%E5%BC%8F%E8%AF%A6%E8%A7%A3/"/>
    <id>https://www.stockclaw.asia/2017/07/02/H-264%E6%A0%87%E5%87%86%EF%BC%88%E4%B8%89%EF%BC%89F4V%E5%B0%81%E8%A3%85%E6%A0%BC%E5%BC%8F%E8%AF%A6%E8%A7%A3/</id>
    <published>2017-07-02T09:27:32.000Z</published>
    <updated>2019-03-31T13:58:42.000Z</updated>
    
    <content type="html"><![CDATA[<center><br><img src="/upload/Warcraft.jpg" alt="这里写图片描述"><br></center><p>F4V是Adobe公司为了迎接高清时代而推出继FLV格式后的支持H.264的流媒体格式。它和FLV主要的区别在于，<span id="more"></span> FLV格式采用的是H263编码，而F4V则支持H.264编码的高清晰视频，码率最高可达50Mbps。</p><p>由于采用H264高清编码，相比于传统的FLV，F4V在同等体积的前提下，能够实现更高的分辨率，并支持更高比特率。随着网络带宽的发展和视频网站的发展，以及人们对视频清晰度越来越高的要求，F4V已经不断取代FLV，流传于更大视频网站，成为网络流媒体主流格式。</p><p>但由于F4V的新兴，各大视频网站采用的F4V标准非常之多，也决定了F4V相比于传统FLV，兼容能力相对还较弱。</p><p>需要注意的是，F4V 和MP4 是兼容的格式，都属于ISMAMP4 容器，但是 F4V 只用来封装H.264视频编码和音频AAC。</p><p>FLV 是Adobe 私有格式，但是也可以用来封装 H.264视频编码、AAC音频编码或H.263视频编码、MP3音频编码。</p><p>所以不能看到扩展名为 flv 就认为不是H.264 编码的F4V，网络上很多后缀FLV的视频，其实质是更高清晰度的F4V。</p><p>F4V格式：</p><p><img src="http://img.blog.csdn.net/20170702165754485?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>F4V是基于ISO MP4格式。ftyp box帮助识别一个特殊文件<br>FlashPlayer不要求强制有ftyp box，只要在在它所支持的编解码类型的限制之内。</p><p><img src="http://img.blog.csdn.net/20170702165807299?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>moov box，FLV文件，仅包含一个moov box, 一个moov box包含一个或多个其他的box.</p><p><img src="http://img.blog.csdn.net/20170702165819601?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>mvhd box ，FLV文件，仅包含一个mvhd box, mvhd box位于mooov box中，定义了playback相关信息，用于正个F4V文件中。</p><p><img src="http://img.blog.csdn.net/20170702165830569?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>trck box，FLV文件，仅包含一个mvhd box, mvhd box位于trck box中，定义了F4V文件中一个单独track对应的信息，并且包含其他box,</p><p><img src="http://img.blog.csdn.net/20170702165843481?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>mdia box, 每个trck box仅含一个mdia box，并且包含其他box, 定义了media track属性</p><p><img src="http://img.blog.csdn.net/20170702165855052?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>minf box，每个mdia box仅含一个 minf box, 并且包含其他box, 定义了 track’s media信息</p><p><img src="http://img.blog.csdn.net/20170702165902855?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>tkhd box, 每个trck box仅含一个mdia box，定义了一个track主要属性。</p><p><img src="http://img.blog.csdn.net/20170702165911802?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>mdhd box, 每个mdia box仅含一个mdhd box，定义了一个media track的属性。</p><p><img src="http://img.blog.csdn.net/20170702165920996?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>stbl box，每个minf box仅含一个stbl box，并且包含其他box, 定义了构建一个track所须要的属性</p><p><img src="http://img.blog.csdn.net/20170702165932942?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>stsd box，每个stbl box仅含一个stsd box，定义了一个sample table中sample描述，一个stsd box包含一个track大量描述，每个包含在track中的media type都对应有一个。</p><p><img src="http://img.blog.csdn.net/20170702165942518?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>stsc box， 每个stbl box仅含一个stsc box，定义了sample对应chunk的映射信息。</p><p><img src="http://img.blog.csdn.net/20170702165951092?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>stts box， 每个stbl box仅含一个stsc box，定义了一个sample table中的time-to-sample映射信息。</p><p><img src="http://img.blog.csdn.net/20170702170001639?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>ctts box , 每个stbl box最多含有一个 ctts box ，也可没有，前面介绍的box都是必须要有的。ctts box定义了一个time-to-sample映射的组合信息。</p><p><img src="http://img.blog.csdn.net/20170702170017030?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>]]></content>
    
    
    <summary type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;/upload/Warcraft.jpg&quot; alt=&quot;这里写图片描述&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;F4V是Adobe公司为了迎接高清时代而推出继FLV格式后的支持H.264的流媒体格式。它和FLV主要的区别在于，</summary>
    
    
    
    <category term="H.264标准" scheme="https://www.stockclaw.asia/categories/H-264%E6%A0%87%E5%87%86/"/>
    
    
    <category term="F4V格式" scheme="https://www.stockclaw.asia/tags/F4V%E6%A0%BC%E5%BC%8F/"/>
    
  </entry>
  
  <entry>
    <title>FFmpeg总结（十一）用ffmpeg进行转格式，Android下播放网络音频流</title>
    <link href="https://www.stockclaw.asia/2017/06/24/FFmpeg%E6%80%BB%E7%BB%93%EF%BC%88%E5%8D%81%E4%B8%80%EF%BC%89%E7%94%A8ffmpeg%E8%BF%9B%E8%A1%8C%E8%BD%AC%E6%A0%BC%E5%BC%8F%EF%BC%8CAndroid%E4%B8%8B%E6%92%AD%E6%94%BE%E7%BD%91%E7%BB%9C%E9%9F%B3%E9%A2%91%E6%B5%81/"/>
    <id>https://www.stockclaw.asia/2017/06/24/FFmpeg%E6%80%BB%E7%BB%93%EF%BC%88%E5%8D%81%E4%B8%80%EF%BC%89%E7%94%A8ffmpeg%E8%BF%9B%E8%A1%8C%E8%BD%AC%E6%A0%BC%E5%BC%8F%EF%BC%8CAndroid%E4%B8%8B%E6%92%AD%E6%94%BE%E7%BD%91%E7%BB%9C%E9%9F%B3%E9%A2%91%E6%B5%81/</id>
    <published>2017-06-24T09:44:43.000Z</published>
    <updated>2019-03-31T13:58:34.000Z</updated>
    
    <content type="html"><![CDATA[<center><br><img src="/upload/assassin.jpg" alt="这里写图片描述"><br></center><p>思路：<br>1、mp3转成pcm(音频数据)，ffmpeg做的事<br>2、OpenSL ES引擎创建AudioPlayer，实际调用了AudioTrack<br><span id="more"></span></p><p>遇到的错误：<br>Error #include nested too deeply<br>原因：c文件互相引用<br>解决方案：</p><ul><li>1、将两个头文件共用的那一部分抽出来单独建一个头文件。</li><li>2、加预处理#ifndef.. #define…#endif</li></ul><p>x86平台没有编译出来so，怀疑存在版本不兼容，编译别的相关so，x86下没有异常。有空这里再更新下原因</p><p><img src="http://img.blog.csdn.net/20170507110911572?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>studio写ndk相当方便：</p><p><img src="http://img.blog.csdn.net/20170507104756342?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p><img src="http://img.blog.csdn.net/20170507104942030?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>工程结构：</p><p><img src="http://img.blog.csdn.net/20170507104526918?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>Java代码：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.hejunlin.ffmpegaudio;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> android.support.v7.app.AppCompatActivity;</span><br><span class="line"><span class="keyword">import</span> android.os.Bundle;</span><br><span class="line"><span class="keyword">import</span> android.view.View;</span><br><span class="line"><span class="keyword">import</span> android.widget.EditText;</span><br><span class="line"><span class="keyword">import</span> android.widget.TextView;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MainActivity</span> <span class="keyword">extends</span> <span class="title class_">AppCompatActivity</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> EditText mInput;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">onCreate</span><span class="params">(Bundle savedInstanceState)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line">        mInput = (EditText) findViewById(R.id.et_input);</span><br><span class="line">     mInput.setText(<span class="string">&quot;http://qzone.60dj.com/huiyuan/201704/19/201704190533197825_35285.mp3&quot;</span>);</span><br><span class="line">        findViewById(R.id.bt_play).setOnClickListener(<span class="keyword">new</span> <span class="title class_">View</span>.OnClickListener() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onClick</span><span class="params">(View view)</span> &#123;</span><br><span class="line">                NativePlayer.play(mInput.getText().toString().trim());</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        findViewById(R.id.bt_pause).setOnClickListener(<span class="keyword">new</span> <span class="title class_">View</span>.OnClickListener() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onClick</span><span class="params">(View view)</span> &#123;</span><br><span class="line">                NativePlayer.stop();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>NativePlayer:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.hejunlin.ffmpegaudio;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Created by hejunlin on 17/5/6.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NativePlayer</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        System.loadLibrary(<span class="string">&quot;NativePlayer&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">native</span> <span class="keyword">void</span> <span class="title function_">play</span><span class="params">(String url)</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">native</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><br>布局文件：<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;utf-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">RelativeLayout</span></span></span><br><span class="line"><span class="tag">    <span class="attr">xmlns:android</span>=<span class="string">&quot;http://schemas.android.com/apk/res/android&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">xmlns:tools</span>=<span class="string">&quot;http://schemas.android.com/tools&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:id</span>=<span class="string">&quot;@+id/activity_main&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">tools:context</span>=<span class="string">&quot;com.hejunlin.ffmpegaudio.MainActivity&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">TextView</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/tv_input&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:padding</span>=<span class="string">&quot;10dp&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_marginTop</span>=<span class="string">&quot;30dp&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:text</span>=<span class="string">&quot;播放链接:&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:textSize</span>=<span class="string">&quot;20sp&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">EditText</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/et_input&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_toRightOf</span>=<span class="string">&quot;@id/tv_input&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:padding</span>=<span class="string">&quot;10dp&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">LinearLayout</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_below</span>=<span class="string">&quot;@id/et_input&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:orientation</span>=<span class="string">&quot;horizontal&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">Button</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:id</span>=<span class="string">&quot;@+id/bt_play&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:layout_width</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:layout_marginTop</span>=<span class="string">&quot;10dp&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:layout_marginLeft</span>=<span class="string">&quot;60dp&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:background</span>=<span class="string">&quot;@drawable/button_shape&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:textColor</span>=<span class="string">&quot;@color/white&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:text</span>=<span class="string">&quot;播放&quot;</span> /&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">Button</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:id</span>=<span class="string">&quot;@+id/bt_pause&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:layout_width</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:layout_marginTop</span>=<span class="string">&quot;10dp&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:background</span>=<span class="string">&quot;@drawable/button_shape&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:textColor</span>=<span class="string">&quot;@color/white&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:layout_marginLeft</span>=<span class="string">&quot;80dp&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:text</span>=<span class="string">&quot;暂停&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">LinearLayout</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">RelativeLayout</span>&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure></p><p>jni相关代码：<br>OpenSL_ES_Core.c<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Created by hejunlin on 17/5/6.</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;OpenSL_ES_Core.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;FFmpegCore.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;assert.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;jni.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;SLES/OpenSLES.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;SLES/OpenSLES_Android.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// for native asset manager</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;android/asset_manager.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;android/asset_manager_jni.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;log.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// engine interfaces</span></span><br><span class="line"><span class="type">static</span> SLObjectItf engineObject = <span class="literal">NULL</span>;</span><br><span class="line"><span class="type">static</span> SLEngineItf engineEngine;</span><br><span class="line"></span><br><span class="line"><span class="comment">// output mix interfaces</span></span><br><span class="line"><span class="type">static</span> SLObjectItf outputMixObject = <span class="literal">NULL</span>;</span><br><span class="line"><span class="type">static</span> SLEnvironmentalReverbItf outputMixEnvironmentalReverb = <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// buffer queue player interfaces</span></span><br><span class="line"><span class="type">static</span> SLObjectItf bqPlayerObject = <span class="literal">NULL</span>;</span><br><span class="line"><span class="type">static</span> SLPlayItf bqPlayerPlay;</span><br><span class="line"><span class="type">static</span> SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;</span><br><span class="line"><span class="type">static</span> SLEffectSendItf bqPlayerEffectSend;</span><br><span class="line"><span class="type">static</span> SLMuteSoloItf bqPlayerMuteSolo;</span><br><span class="line"><span class="type">static</span> SLVolumeItf bqPlayerVolume;</span><br><span class="line"></span><br><span class="line"><span class="comment">// aux effect on the output mix, used by the buffer queue player</span></span><br><span class="line"><span class="type">static</span> <span class="type">const</span> SLEnvironmentalReverbSettings reverbSettings =</span><br><span class="line">        SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;</span><br><span class="line"></span><br><span class="line"><span class="type">static</span> <span class="type">void</span> *buffer;</span><br><span class="line"><span class="type">static</span> <span class="type">size_t</span> bufferSize;</span><br><span class="line"></span><br><span class="line"><span class="comment">// this callback handler is called every time a buffer finishes playing</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">bqPlayerCallback</span><span class="params">(SLAndroidSimpleBufferQueueItf bq, <span class="type">void</span> *context)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;&gt;&gt; buffere queue callback&quot;</span>);</span><br><span class="line">    <span class="built_in">assert</span>(bq == bqPlayerBufferQueue);</span><br><span class="line">    bufferSize = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">//assert(NULL == context);</span></span><br><span class="line">    <span class="built_in">getPCM</span>(&amp;buffer, &amp;bufferSize);</span><br><span class="line">    <span class="comment">// for streaming playback, replace this test by logic to find and fill the next buffer</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="literal">NULL</span> != buffer &amp;&amp; <span class="number">0</span> != bufferSize) &#123;</span><br><span class="line">        SLresult result;</span><br><span class="line">        <span class="comment">// enqueue another buffer</span></span><br><span class="line">        result = (*bqPlayerBufferQueue)-&gt;<span class="built_in">Enqueue</span>(bqPlayerBufferQueue, buffer,</span><br><span class="line">                                                 bufferSize);</span><br><span class="line">        <span class="comment">// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,</span></span><br><span class="line">        <span class="comment">// which for this code example would indicate a programming error</span></span><br><span class="line">        <span class="built_in">assert</span>(SL_RESULT_SUCCESS == result);</span><br><span class="line"></span><br><span class="line">        (<span class="type">void</span>)result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">initOpenSLES</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;&gt;&gt; initOpenSLES...&quot;</span>);</span><br><span class="line">    SLresult result;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 1、create engine</span></span><br><span class="line">    result = <span class="built_in">slCreateEngine</span>(&amp;engineObject, <span class="number">0</span>, <span class="literal">NULL</span>, <span class="number">0</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;&gt;&gt; initOpenSLES... step 1, result = %d&quot;</span>, result);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2、realize the engine</span></span><br><span class="line">    result = (*engineObject)-&gt;<span class="built_in">Realize</span>(engineObject, SL_BOOLEAN_FALSE);</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;&gt;&gt; initOpenSLES...step 2, result = %d&quot;</span>, result);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 3、get the engine interface, which is needed in order to create other objects</span></span><br><span class="line">    result = (*engineObject)-&gt;<span class="built_in">GetInterface</span>(engineObject, SL_IID_ENGINE, &amp;engineEngine);</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;&gt;&gt; initOpenSLES...step 3, result = %d&quot;</span>, result);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 4、create output mix, with environmental reverb specified as a non-required interface</span></span><br><span class="line">    <span class="type">const</span> SLInterfaceID ids[<span class="number">1</span>] = &#123;SL_IID_ENVIRONMENTALREVERB&#125;;</span><br><span class="line">    <span class="type">const</span> SLboolean req[<span class="number">1</span>] = &#123;SL_BOOLEAN_FALSE&#125;;</span><br><span class="line">    result = (*engineEngine)-&gt;<span class="built_in">CreateOutputMix</span>(engineEngine, &amp;outputMixObject, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;&gt;&gt; initOpenSLES...step 4, result = %d&quot;</span>, result);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 5、realize the output mix</span></span><br><span class="line">    result = (*outputMixObject)-&gt;<span class="built_in">Realize</span>(outputMixObject, SL_BOOLEAN_FALSE);</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;&gt;&gt; initOpenSLES...step 5, result = %d&quot;</span>, result);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 6、get the environmental reverb interface</span></span><br><span class="line">    <span class="comment">// this could fail if the environmental reverb effect is not available,</span></span><br><span class="line">    <span class="comment">// either because the feature is not present, excessive CPU load, or</span></span><br><span class="line">    <span class="comment">// the required MODIFY_AUDIO_SETTINGS permission was not requested and granted</span></span><br><span class="line">    result = (*outputMixObject)-&gt;<span class="built_in">GetInterface</span>(outputMixObject, SL_IID_ENVIRONMENTALREVERB,</span><br><span class="line">                                              &amp;outputMixEnvironmentalReverb);</span><br><span class="line">    <span class="keyword">if</span> (SL_RESULT_SUCCESS == result) &#123;</span><br><span class="line">        result = (*outputMixEnvironmentalReverb)-&gt;<span class="built_in">SetEnvironmentalReverbProperties</span>(</span><br><span class="line">                outputMixEnvironmentalReverb, &amp;reverbSettings);</span><br><span class="line">        <span class="built_in">LOGD</span>(<span class="string">&quot;&gt;&gt; initOpenSLES...step 6, result = %d&quot;</span>, result);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// init buffer queue</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">initBufferQueue</span><span class="params">(<span class="type">int</span> rate, <span class="type">int</span> channel, <span class="type">int</span> bitsPerSample)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;&gt;&gt; initBufferQueue&quot;</span>);</span><br><span class="line">    SLresult result;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// configure audio source</span></span><br><span class="line">    SLDataLocator_AndroidSimpleBufferQueue loc_bufq = &#123;SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, <span class="number">2</span>&#125;;</span><br><span class="line">    SLDataFormat_PCM format_pcm;</span><br><span class="line">    format_pcm.formatType = SL_DATAFORMAT_PCM;</span><br><span class="line">    format_pcm.numChannels = channel;</span><br><span class="line">    format_pcm.samplesPerSec = rate * <span class="number">1000</span>;</span><br><span class="line">    format_pcm.bitsPerSample = bitsPerSample;</span><br><span class="line">    format_pcm.containerSize = <span class="number">16</span>;</span><br><span class="line">    <span class="keyword">if</span> (channel == <span class="number">2</span>)</span><br><span class="line">        format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;</span><br><span class="line">    format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;</span><br><span class="line">    SLDataSource audioSrc = &#123;&amp;loc_bufq, &amp;format_pcm&#125;;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// configure audio sink</span></span><br><span class="line">    SLDataLocator_OutputMix loc_outmix = &#123;SL_DATALOCATOR_OUTPUTMIX, outputMixObject&#125;;</span><br><span class="line">    SLDataSink audioSnk = &#123;&amp;loc_outmix, <span class="literal">NULL</span>&#125;;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// create audio player</span></span><br><span class="line">    <span class="type">const</span> SLInterfaceID ids[<span class="number">3</span>] = &#123;SL_IID_BUFFERQUEUE, SL_IID_EFFECTSEND,</span><br><span class="line">            <span class="comment">/*SL_IID_MUTESOLO,*/</span> SL_IID_VOLUME&#125;;</span><br><span class="line">    <span class="type">const</span> SLboolean req[<span class="number">3</span>] = &#123;SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE,</span><br><span class="line">            <span class="comment">/*SL_BOOLEAN_TRUE,*/</span> SL_BOOLEAN_TRUE&#125;;</span><br><span class="line">    result = (*engineEngine)-&gt;<span class="built_in">CreateAudioPlayer</span>(engineEngine, &amp;bqPlayerObject, &amp;audioSrc, &amp;audioSnk,</span><br><span class="line">                                                <span class="number">3</span>, ids, req);</span><br><span class="line">    <span class="built_in">assert</span>(SL_RESULT_SUCCESS == result);</span><br><span class="line">    (<span class="type">void</span>)result;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// realize the player</span></span><br><span class="line">    result = (*bqPlayerObject)-&gt;<span class="built_in">Realize</span>(bqPlayerObject, SL_BOOLEAN_FALSE);</span><br><span class="line">    <span class="built_in">assert</span>(SL_RESULT_SUCCESS == result);</span><br><span class="line">    (<span class="type">void</span>)result;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// get the play interface</span></span><br><span class="line">    result = (*bqPlayerObject)-&gt;<span class="built_in">GetInterface</span>(bqPlayerObject, SL_IID_PLAY, &amp;bqPlayerPlay);</span><br><span class="line">    <span class="built_in">assert</span>(SL_RESULT_SUCCESS == result);</span><br><span class="line">    (<span class="type">void</span>)result;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// get the buffer queue interface</span></span><br><span class="line">    result = (*bqPlayerObject)-&gt;<span class="built_in">GetInterface</span>(bqPlayerObject, SL_IID_BUFFERQUEUE,</span><br><span class="line">                                             &amp;bqPlayerBufferQueue);</span><br><span class="line">    <span class="built_in">assert</span>(SL_RESULT_SUCCESS == result);</span><br><span class="line">    (<span class="type">void</span>)result;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// register callback on the buffer queue</span></span><br><span class="line">    result = (*bqPlayerBufferQueue)-&gt;<span class="built_in">RegisterCallback</span>(bqPlayerBufferQueue, bqPlayerCallback, <span class="literal">NULL</span>);</span><br><span class="line">    <span class="built_in">assert</span>(SL_RESULT_SUCCESS == result);</span><br><span class="line">    (<span class="type">void</span>)result;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// get the effect send interface</span></span><br><span class="line">    result = (*bqPlayerObject)-&gt;<span class="built_in">GetInterface</span>(bqPlayerObject, SL_IID_EFFECTSEND,</span><br><span class="line">                                             &amp;bqPlayerEffectSend);</span><br><span class="line">    <span class="built_in">assert</span>(SL_RESULT_SUCCESS == result);</span><br><span class="line">    (<span class="type">void</span>)result;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// get the volume interface</span></span><br><span class="line">    result = (*bqPlayerObject)-&gt;<span class="built_in">GetInterface</span>(bqPlayerObject, SL_IID_VOLUME, &amp;bqPlayerVolume);</span><br><span class="line">    <span class="built_in">assert</span>(SL_RESULT_SUCCESS == result);</span><br><span class="line">    (<span class="type">void</span>)result;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// set the player&#x27;s state to playing</span></span><br><span class="line">    result = (*bqPlayerPlay)-&gt;<span class="built_in">SetPlayState</span>(bqPlayerPlay, SL_PLAYSTATE_PLAYING);</span><br><span class="line">    <span class="built_in">assert</span>(SL_RESULT_SUCCESS == result);</span><br><span class="line">    (<span class="type">void</span>)result;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// stop the native audio system</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">stop</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// destroy buffer queue audio player object, and invalidate all associated interfaces</span></span><br><span class="line">    <span class="keyword">if</span> (bqPlayerObject != <span class="literal">NULL</span>) &#123;</span><br><span class="line">        (*bqPlayerObject)-&gt;<span class="built_in">Destroy</span>(bqPlayerObject);</span><br><span class="line">        bqPlayerObject = <span class="literal">NULL</span>;</span><br><span class="line">        bqPlayerPlay = <span class="literal">NULL</span>;</span><br><span class="line">        bqPlayerBufferQueue = <span class="literal">NULL</span>;</span><br><span class="line">        bqPlayerEffectSend = <span class="literal">NULL</span>;</span><br><span class="line">        bqPlayerMuteSolo = <span class="literal">NULL</span>;</span><br><span class="line">        bqPlayerVolume = <span class="literal">NULL</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// destroy output mix object, and invalidate all associated interfaces</span></span><br><span class="line">    <span class="keyword">if</span> (outputMixObject != <span class="literal">NULL</span>) &#123;</span><br><span class="line">        (*outputMixObject)-&gt;<span class="built_in">Destroy</span>(outputMixObject);</span><br><span class="line">        outputMixObject = <span class="literal">NULL</span>;</span><br><span class="line">        outputMixEnvironmentalReverb = <span class="literal">NULL</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// destroy engine object, and invalidate all associated interfaces</span></span><br><span class="line">    <span class="keyword">if</span> (engineObject != <span class="literal">NULL</span>) &#123;</span><br><span class="line">        (*engineObject)-&gt;<span class="built_in">Destroy</span>(engineObject);</span><br><span class="line">        engineObject = <span class="literal">NULL</span>;</span><br><span class="line">        engineEngine = <span class="literal">NULL</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 释放FFmpeg解码器</span></span><br><span class="line">    <span class="built_in">releaseFFmpeg</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">play</span><span class="params">(<span class="type">char</span> *url)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> rate, channel;</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;...get url=%s&quot;</span>, url);</span><br><span class="line">    <span class="comment">// 1、初始化FFmpeg解码器</span></span><br><span class="line">    <span class="built_in">initFFmpeg</span>(&amp;rate, &amp;channel, url);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2、初始化OpenSLES</span></span><br><span class="line">    <span class="built_in">initOpenSLES</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 3、初始化BufferQueue</span></span><br><span class="line">    <span class="built_in">initBufferQueue</span>(rate, channel, SL_PCMSAMPLEFORMAT_FIXED_16);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 4、启动音频播放</span></span><br><span class="line">    <span class="built_in">bqPlayerCallback</span>(bqPlayerBufferQueue, <span class="literal">NULL</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>FFmpegCore.c<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;log.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;FFmpegCore.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;libavcodec/avcodec.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;libavformat/avformat.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;libswscale/swscale.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;libswresample/swresample.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;libavutil/samplefmt.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;SLES/OpenSLES.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;SLES/OpenSLES_Android.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">uint8_t</span> *outputBuffer;</span><br><span class="line"><span class="type">size_t</span> outputBufferSize;</span><br><span class="line"></span><br><span class="line">AVPacket packet;</span><br><span class="line"><span class="type">int</span> audioStream;</span><br><span class="line">AVFrame *aFrame;</span><br><span class="line">SwrContext *swr;</span><br><span class="line">AVFormatContext *aFormatCtx;</span><br><span class="line">AVCodecContext *aCodecCtx;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">initFFmpeg</span><span class="params">(<span class="type">int</span> *rate, <span class="type">int</span> *channel, <span class="type">char</span> *url)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">av_register_all</span>();</span><br><span class="line">    aFormatCtx = <span class="built_in">avformat_alloc_context</span>();</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;ffmpeg get url=:%s&quot;</span>, url);</span><br><span class="line">    <span class="comment">// 网络音频流</span></span><br><span class="line">    <span class="type">char</span> *file_name = url;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Open audio file</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">avformat_open_input</span>(&amp;aFormatCtx, file_name, <span class="literal">NULL</span>, <span class="literal">NULL</span>) != <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="built_in">LOGE</span>(<span class="string">&quot;Couldn&#x27;t open file:%s\n&quot;</span>, file_name);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>; <span class="comment">// Couldn&#x27;t open file</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Retrieve stream information</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">avformat_find_stream_info</span>(aFormatCtx, <span class="literal">NULL</span>) &lt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="built_in">LOGE</span>(<span class="string">&quot;Couldn&#x27;t find stream information.&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Find the first audio stream</span></span><br><span class="line">    <span class="type">int</span> i;</span><br><span class="line">    audioStream = <span class="number">-1</span>;</span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; aFormatCtx-&gt;nb_streams; i++) &#123;</span><br><span class="line">        <span class="keyword">if</span> (aFormatCtx-&gt;streams[i]-&gt;codec-&gt;codec_type == AVMEDIA_TYPE_AUDIO &amp;&amp;</span><br><span class="line">            audioStream &lt; <span class="number">0</span>) &#123;</span><br><span class="line">            audioStream = i;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (audioStream == <span class="number">-1</span>) &#123;</span><br><span class="line">        <span class="built_in">LOGE</span>(<span class="string">&quot;Couldn&#x27;t find audio stream!&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Get a pointer to the codec context for the video stream</span></span><br><span class="line">    aCodecCtx = aFormatCtx-&gt;streams[audioStream]-&gt;codec;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Find the decoder for the audio stream</span></span><br><span class="line">    AVCodec *aCodec = <span class="built_in">avcodec_find_decoder</span>(aCodecCtx-&gt;codec_id);</span><br><span class="line">    <span class="keyword">if</span> (!aCodec) &#123;</span><br><span class="line">        <span class="built_in">fprintf</span>(stderr, <span class="string">&quot;Unsupported codec!\n&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">avcodec_open2</span>(aCodecCtx, aCodec, <span class="literal">NULL</span>) &lt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="built_in">LOGE</span>(<span class="string">&quot;Could not open codec.&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>; <span class="comment">// Could not open codec</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    aFrame = <span class="built_in">av_frame_alloc</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 设置格式转换</span></span><br><span class="line">    swr = <span class="built_in">swr_alloc</span>();</span><br><span class="line">    <span class="built_in">av_opt_set_int</span>(swr, <span class="string">&quot;in_channel_layout&quot;</span>,  aCodecCtx-&gt;channel_layout, <span class="number">0</span>);</span><br><span class="line">    <span class="built_in">av_opt_set_int</span>(swr, <span class="string">&quot;out_channel_layout&quot;</span>, aCodecCtx-&gt;channel_layout,  <span class="number">0</span>);</span><br><span class="line">    <span class="built_in">av_opt_set_int</span>(swr, <span class="string">&quot;in_sample_rate&quot;</span>,     aCodecCtx-&gt;sample_rate, <span class="number">0</span>);</span><br><span class="line">    <span class="built_in">av_opt_set_int</span>(swr, <span class="string">&quot;out_sample_rate&quot;</span>,    aCodecCtx-&gt;sample_rate, <span class="number">0</span>);</span><br><span class="line">    <span class="built_in">av_opt_set_sample_fmt</span>(swr, <span class="string">&quot;in_sample_fmt&quot;</span>,  aCodecCtx-&gt;sample_fmt, <span class="number">0</span>);</span><br><span class="line">    <span class="built_in">av_opt_set_sample_fmt</span>(swr, <span class="string">&quot;out_sample_fmt&quot;</span>, AV_SAMPLE_FMT_S16,  <span class="number">0</span>);</span><br><span class="line">    <span class="built_in">swr_init</span>(swr);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 分配PCM数据缓存</span></span><br><span class="line">    outputBufferSize = <span class="number">8196</span>;</span><br><span class="line">    outputBuffer = (<span class="type">uint8_t</span> *) <span class="built_in">malloc</span>(<span class="built_in">sizeof</span>(<span class="type">uint8_t</span>) * outputBufferSize);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 返回sample rate和channels</span></span><br><span class="line">    *rate = aCodecCtx-&gt;sample_rate;</span><br><span class="line">    *channel = aCodecCtx-&gt;channels;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取PCM数据, 自动回调获取</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">getPCM</span><span class="params">(<span class="type">void</span> **pcm, <span class="type">size_t</span> *pcmSize)</span> </span>&#123;</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;&gt;&gt; getPcm&quot;</span>);</span><br><span class="line">    <span class="keyword">while</span> (<span class="built_in">av_read_frame</span>(aFormatCtx, &amp;packet) &gt;= <span class="number">0</span>) &#123;</span><br><span class="line"></span><br><span class="line">        <span class="type">int</span> frameFinished = <span class="number">0</span>;</span><br><span class="line">        <span class="comment">// Is this a packet from the audio stream?</span></span><br><span class="line">        <span class="keyword">if</span> (packet.stream_index == audioStream) &#123;</span><br><span class="line">            <span class="built_in">avcodec_decode_audio4</span>(aCodecCtx, aFrame, &amp;frameFinished, &amp;packet);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (frameFinished) &#123;</span><br><span class="line">                <span class="comment">// data_size为音频数据所占的字节数</span></span><br><span class="line">                <span class="type">int</span> data_size = <span class="built_in">av_samples_get_buffer_size</span>(</span><br><span class="line">                        aFrame-&gt;linesize, aCodecCtx-&gt;channels,</span><br><span class="line">                        aFrame-&gt;nb_samples, aCodecCtx-&gt;sample_fmt, <span class="number">1</span>);</span><br><span class="line">                <span class="built_in">LOGD</span>(<span class="string">&quot;&gt;&gt; getPcm data_size=%d&quot;</span>, data_size);</span><br><span class="line">                <span class="comment">// 这里内存再分配可能存在问题</span></span><br><span class="line">                <span class="keyword">if</span> (data_size &gt; outputBufferSize) &#123;</span><br><span class="line">                    outputBufferSize = data_size;</span><br><span class="line">                    outputBuffer = (<span class="type">uint8_t</span> *) <span class="built_in">realloc</span>(outputBuffer,</span><br><span class="line">                                                       <span class="built_in">sizeof</span>(<span class="type">uint8_t</span>) * outputBufferSize);</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 音频格式转换</span></span><br><span class="line">                <span class="built_in">swr_convert</span>(swr, &amp;outputBuffer, aFrame-&gt;nb_samples,</span><br><span class="line">                            (<span class="type">uint8_t</span> <span class="type">const</span> **) (aFrame-&gt;extended_data),</span><br><span class="line">                        aFrame-&gt;nb_samples);</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 返回pcm数据</span></span><br><span class="line">                *pcm = outputBuffer;</span><br><span class="line">                *pcmSize = data_size;</span><br><span class="line">                <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 释放相关资源</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">releaseFFmpeg</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">av_packet_unref</span>(&amp;packet);</span><br><span class="line">    <span class="built_in">av_free</span>(outputBuffer);</span><br><span class="line">    <span class="built_in">av_free</span>(aFrame);</span><br><span class="line">    <span class="built_in">avcodec_close</span>(aCodecCtx);</span><br><span class="line">    <span class="built_in">avformat_close_input</span>(&amp;aFormatCtx);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure><br>NativePlayer.c<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Created by hejunlin on 17/5/6.</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;log.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;com_hejunlin_ffmpegaudio_NativePlayer.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;OpenSL_ES_Core.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function">JNIEXPORT <span class="type">void</span> JNICALL</span></span><br><span class="line"><span class="function"><span class="title">Java_com_hejunlin_ffmpegaudio_NativePlayer_play</span><span class="params">(JNIEnv *env, jclass type, jstring url_)</span> </span>&#123;</span><br><span class="line">    <span class="type">const</span> <span class="type">char</span> *url = (*env)-&gt;<span class="built_in">GetStringUTFChars</span>(env, url_, <span class="number">0</span>);</span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;start playaudio... url=%s&quot;</span>, url);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">play</span>(url);</span><br><span class="line">    (*env)-&gt;<span class="built_in">ReleaseStringUTFChars</span>(env, url_, url);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">JNIEXPORT <span class="type">void</span> JNICALL</span></span><br><span class="line"><span class="function"><span class="title">Java_com_hejunlin_ffmpegaudio_NativePlayer_stop</span><span class="params">(JNIEnv *env, jclass type)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">LOGD</span>(<span class="string">&quot;stop&quot;</span>);</span><br><span class="line">    <span class="built_in">stop</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>通过cmake，或ndk-build都可以编译，会生成一个NativePlayer.so</p><p><img src="http://img.blog.csdn.net/20170507110500148?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>效果图：</p><p><img src="http://img.blog.csdn.net/20170507103743452?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>log输出如下：<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.476</span> <span class="number">6001</span>-<span class="number">6097</span>/com.hejunlin.ffmpegaudio D/Surface: Surface::setBuffersDimensions(<span class="built_in">this</span>=<span class="number">0xf45b6300</span>,w=<span class="number">1080</span>,h=<span class="number">1920</span>)</span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.491</span> <span class="number">6001</span>-<span class="number">6097</span>/com.hejunlin.ffmpegaudio D/Surface: Surface::setBuffersDimensions(<span class="built_in">this</span>=<span class="number">0xf45b6300</span>,w=<span class="number">1080</span>,h=<span class="number">1920</span>)</span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.516</span> <span class="number">6001</span>-<span class="number">6097</span>/com.hejunlin.ffmpegaudio D/Surface: Surface::setBuffersDimensions(<span class="built_in">this</span>=<span class="number">0xf45b6300</span>,w=<span class="number">1080</span>,h=<span class="number">1920</span>)</span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.525</span> <span class="number">6001</span>-<span class="number">6097</span>/com.hejunlin.ffmpegaudio D/Surface: Surface::setBuffersDimensions(<span class="built_in">this</span>=<span class="number">0xf45b6300</span>,w=<span class="number">1080</span>,h=<span class="number">1920</span>)</span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.542</span> <span class="number">6001</span>-<span class="number">6097</span>/com.hejunlin.ffmpegaudio D/Surface: Surface::setBuffersDimensions(<span class="built_in">this</span>=<span class="number">0xf45b6300</span>,w=<span class="number">1080</span>,h=<span class="number">1920</span>)</span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.556</span> <span class="number">6001</span>-<span class="number">6097</span>/com.hejunlin.ffmpegaudio D/Surface: Surface::setBuffersDimensions(<span class="built_in">this</span>=<span class="number">0xf45b6300</span>,w=<span class="number">1080</span>,h=<span class="number">1920</span>)</span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.573</span> <span class="number">6001</span>-<span class="number">6097</span>/com.hejunlin.ffmpegaudio D/Surface: Surface::setBuffersDimensions(<span class="built_in">this</span>=<span class="number">0xf45b6300</span>,w=<span class="number">1080</span>,h=<span class="number">1920</span>)</span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.577</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio W/linker: libNativePlayer.so: unused DT entry: type <span class="number">0x6ffffffe</span> arg <span class="number">0x1414</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.577</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio W/linker: libNativePlayer.so: unused DT entry: type <span class="number">0x6fffffff</span> arg <span class="number">0x4</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.578</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio W/linker: libavcodec-<span class="number">57.</span>so: unused DT entry: type <span class="number">0x6ffffffe</span> arg <span class="number">0x5da4</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.578</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio W/linker: libavcodec-<span class="number">57.</span>so: unused DT entry: type <span class="number">0x6fffffff</span> arg <span class="number">0x2</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.578</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio W/linker: libavformat-<span class="number">57.</span>so: unused DT entry: type <span class="number">0x6ffffffe</span> arg <span class="number">0x6408</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.578</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio W/linker: libavformat-<span class="number">57.</span>so: unused DT entry: type <span class="number">0x6fffffff</span> arg <span class="number">0x2</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.578</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio W/linker: libswresample-<span class="number">2.</span>so: unused DT entry: type <span class="number">0x6ffffffe</span> arg <span class="number">0xcd4</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.578</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio W/linker: libswresample-<span class="number">2.</span>so: unused DT entry: type <span class="number">0x6fffffff</span> arg <span class="number">0x1</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.578</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio W/linker: libswscale-<span class="number">4.</span>so: unused DT entry: type <span class="number">0x6ffffffe</span> arg <span class="number">0xd70</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.578</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio W/linker: libswscale-<span class="number">4.</span>so: unused DT entry: type <span class="number">0x6fffffff</span> arg <span class="number">0x1</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.589</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/NativePlayer.c: Java_com_hejunlin_ffmpegaudio_NativePlayer_play:start playaudio... url=http://qzone.60dj.com/huiyuan/201704/19/201704190533197825_35285.mp3</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.589</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: play:...get url=http://qzone.60dj.com/huiyuan/201704/19/201704190533197825_35285.mp3</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.590</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: initFFmpeg:ffmpeg get url=:http://qzone.60dj.com/huiyuan/201704/19/201704190533197825_35285.mp3</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.696</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D/libc-netbsd: getaddrinfo: qzone.60dj.com get result from proxy &gt;&gt;</span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.949</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:&gt;&gt; initOpenSLES...</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.950</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:&gt;&gt; initOpenSLES... step 1, result = 0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.950</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:&gt;&gt; initOpenSLES...step 2, result = 0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.950</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:&gt;&gt; initOpenSLES...step 3, result = 0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.950</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:&gt;&gt; initOpenSLES...step 4, result = 0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.950</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:&gt;&gt; initOpenSLES...step 5, result = 0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.950</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio W/libOpenSLES: Leaving Object::GetInterface (SL_RESULT_FEATURE_UNSUPPORTED)</span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.950</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initBufferQueue:&gt;&gt; initBufferQueue</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.951</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio V/AudioTrack: set(): streamType <span class="number">3</span>, sampleRate <span class="number">44100</span>, format <span class="number">0x1</span>, channelMask <span class="number">0x3</span>, frameCount <span class="number">0</span>, flags #<span class="number">0</span>, notificationFrames <span class="number">0</span>, sessionId <span class="number">774</span>, transferType <span class="number">0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.951</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio V/AudioTrack: set() streamType <span class="number">3</span> frameCount <span class="number">0</span> flags <span class="number">0000</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.951</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D/AudioTrack: audiotrack <span class="number">0xf459cd80</span> set Type <span class="number">3</span>, rate <span class="number">44100</span>, fmt <span class="number">1</span>, chn <span class="number">3</span>, fcnt <span class="number">0</span>, flags <span class="number">0000</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.951</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D/AudioTrack: mChannelMask <span class="number">0x3</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.953</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio V/AudioTrack: createTrack_l() output <span class="number">2</span> afLatency <span class="number">21</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.953</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio V/AudioTrack: afFrameCount=<span class="number">1024</span>, minBufCount=<span class="number">1</span>, afSampleRate=<span class="number">48000</span>, afLatency=<span class="number">21</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.953</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio V/AudioTrack: minFrameCount: <span class="number">2822</span>, afFrameCount=<span class="number">1024</span>, minBufCount=<span class="number">3</span>, sampleRate=<span class="number">44100</span>, afSampleRate=<span class="number">48000</span>, afLatency=<span class="number">21</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.954</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D/AudioTrackCenter: addTrack, trackId:<span class="number">0xdaf0c000</span>, frameCount:<span class="number">2822</span>, sampleRate:<span class="number">44100</span>, trackPtr:<span class="number">0xf459cd80</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.954</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D/AudioTrackCenter: mAfSampleRate <span class="number">48000</span>, sampleRate <span class="number">44100</span>, AfFrameCount <span class="number">1024</span> , mAfSampleRate <span class="number">48000</span>, frameCount <span class="number">2822</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.979</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: bqPlayerCallback:&gt;&gt; buffere queue callback</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.979</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:&gt;&gt; getPcm</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.979</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D/AudioTrackShared: front(<span class="number">0x0</span>), mIsOut <span class="number">1</span>, avail <span class="number">2822</span>, mFrameCount <span class="number">2822</span>, filled <span class="number">0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.979</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio V/AudioTrack: obtainBuffer(<span class="number">940</span>) returned <span class="number">2822</span> = <span class="number">940</span> + <span class="number">1882</span> err <span class="number">0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.979</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D/AudioTrackShared: front(<span class="number">0x0</span>), mIsOut <span class="number">1</span>, interrupt() FUTEX_WAKE</span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.979</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D/AudioTrack: audiotrack <span class="number">0xf459cd80</span> stop done</span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6001</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:&gt;&gt; getPcm data_size=188</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D/AudioTrackShared: front(<span class="number">0x0</span>), mIsOut <span class="number">1</span>, avail <span class="number">2822</span>, mFrameCount <span class="number">2822</span>, filled <span class="number">0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio V/AudioTrack: obtainBuffer(<span class="number">940</span>) returned <span class="number">2822</span> = <span class="number">940</span> + <span class="number">1882</span> err <span class="number">0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D/AudioTrackShared: front(<span class="number">0x0</span>), mIsOut <span class="number">1</span>, avail <span class="number">2775</span>, mFrameCount <span class="number">2822</span>, filled <span class="number">47</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio V/AudioTrack: obtainBuffer(<span class="number">893</span>) returned <span class="number">2775</span> = <span class="number">893</span> + <span class="number">1882</span> err <span class="number">0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: bqPlayerCallback:&gt;&gt; buffere queue callback</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:&gt;&gt; getPcm</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:&gt;&gt; getPcm data_size=4608</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D/AudioTrackShared: front(<span class="number">0x0</span>), mIsOut <span class="number">1</span>, avail <span class="number">1882</span>, mFrameCount <span class="number">2822</span>, filled <span class="number">940</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio V/AudioTrack: obtainBuffer(<span class="number">940</span>) returned <span class="number">1882</span> = <span class="number">940</span> + <span class="number">942</span> err <span class="number">0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D/AudioTrackShared: front(<span class="number">0x0</span>), mIsOut <span class="number">1</span>, avail <span class="number">1623</span>, mFrameCount <span class="number">2822</span>, filled <span class="number">1199</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio V/AudioTrack: obtainBuffer(<span class="number">681</span>) returned <span class="number">1623</span> = <span class="number">681</span> + <span class="number">942</span> err <span class="number">0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: bqPlayerCallback:&gt;&gt; buffere queue callback</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.980</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:&gt;&gt; getPcm</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.981</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:&gt;&gt; getPcm data_size=4608</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.981</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D/AudioTrackShared: front(<span class="number">0x0</span>), mIsOut <span class="number">1</span>, avail <span class="number">942</span>, mFrameCount <span class="number">2822</span>, filled <span class="number">1880</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.981</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio V/AudioTrack: obtainBuffer(<span class="number">940</span>) returned <span class="number">942</span> = <span class="number">940</span> + <span class="number">2</span> err <span class="number">0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.981</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D/AudioTrackShared: front(<span class="number">0x0</span>), mIsOut <span class="number">1</span>, avail <span class="number">471</span>, mFrameCount <span class="number">2822</span>, filled <span class="number">2351</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.981</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio V/AudioTrack: obtainBuffer(<span class="number">469</span>) returned <span class="number">471</span> = <span class="number">469</span> + <span class="number">2</span> err <span class="number">0</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.981</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: bqPlayerCallback:&gt;&gt; buffere queue callback</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.981</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:&gt;&gt; getPcm</span></span><br><span class="line"><span class="number">05</span>-<span class="number">07</span> <span class="number">10</span>:<span class="number">14</span>:<span class="number">04.981</span> <span class="number">6001</span>-<span class="number">6681</span>/com.hejunlin.ffmpegaudio D<span class="comment">//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:&gt;&gt; getPcm data_size=4608</span></span><br></pre></td></tr></table></figure></p>]]></content>
    
    
    <summary type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;/upload/assassin.jpg&quot; alt=&quot;这里写图片描述&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;思路：&lt;br&gt;1、mp3转成pcm(音频数据)，ffmpeg做的事&lt;br&gt;2、OpenSL ES引擎创建AudioPlayer，实际调用了AudioTrack&lt;br&gt;</summary>
    
    
    
    <category term="ffmpeg" scheme="https://www.stockclaw.asia/categories/ffmpeg/"/>
    
    
    <category term="OpenSL ES" scheme="https://www.stockclaw.asia/tags/OpenSL-ES/"/>
    
    <category term="ffmpeg" scheme="https://www.stockclaw.asia/tags/ffmpeg/"/>
    
  </entry>
  
  <entry>
    <title>FFmpeg总结（十二）用ffmpeg与nginx实现直播多路流并发播放</title>
    <link href="https://www.stockclaw.asia/2017/06/24/FFmpeg%E6%80%BB%E7%BB%93%EF%BC%88%E5%8D%81%E4%BA%8C%EF%BC%89%E7%94%A8ffmpeg%E4%B8%8Enginx%E5%AE%9E%E7%8E%B0%E7%9B%B4%E6%92%AD%E5%A4%9A%E8%B7%AF%E6%B5%81%E5%B9%B6%E5%8F%91%E6%92%AD%E6%94%BE/"/>
    <id>https://www.stockclaw.asia/2017/06/24/FFmpeg%E6%80%BB%E7%BB%93%EF%BC%88%E5%8D%81%E4%BA%8C%EF%BC%89%E7%94%A8ffmpeg%E4%B8%8Enginx%E5%AE%9E%E7%8E%B0%E7%9B%B4%E6%92%AD%E5%A4%9A%E8%B7%AF%E6%B5%81%E5%B9%B6%E5%8F%91%E6%92%AD%E6%94%BE/</id>
    <published>2017-06-24T09:31:32.000Z</published>
    <updated>2019-03-31T13:58:28.000Z</updated>
    
    <content type="html"><![CDATA[<center><br><img src="/upload/FinalFantasy.jpg" alt="这里写图片描述"><br></center><p>一、下载 nginx 和 nginx-rtmp源码：<br><span id="more"></span><br><a href="http://nginx.org/download/nginx-1.5.10.tar.gz">http://nginx.org/download/nginx-1.5.10.tar.gz</a><br><a href="https://github.com/arut/nginx-rtmp-module/archive/master.zip">https://github.com/arut/nginx-rtmp-module/archive/master.zip</a></p><p>二、编译安装：</p><ul><li>cd nginx-1.5.10</li><li>./configure –with-http_ssl_module –add-module=../nginx-rtmp-module-master</li><li>make</li><li>make install</li></ul><p>三、浏览器输入localhost:8010（默认80，由于其他服务在用，这里用8010），得到如下：</p><center><br><img src="http://img.blog.csdn.net/20170507151721696?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"><br></center><p>配置nginx支持rtmp，找到nginx.cnf,在http节点结束后加入rtmp节点，如下：<br><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">rtmp &#123;</span><br><span class="line">    server &#123;</span><br><span class="line">            listen 1935;//监听1935端口</span><br><span class="line"></span><br><span class="line">            application yuiop &#123;//为什么叫yuiop？你懂的啦</span><br><span class="line">                    live on;</span><br><span class="line">                    record off;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>四、FFmpeg开始推流，先推一个直播流来直播</p><p>接下来开始看下服务器流是否可看，开始拉流播放<br><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ffplay rtmp://xxx.xxx.xxx.xxx:1935/yuiop/live</span><br></pre></td></tr></table></figure><br>也可以在网页端口写点js代码，也能支持播放，效果如下：</p><p><img src="http://img.blog.csdn.net/20170507161818546?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>推一个流，拉一个流不过瘾，直播可是，同时有n多个流在推拉，接着来，推拉两个，很自然也成功了。</p><p><img src="http://img.blog.csdn.net/20170507161629380?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p><p>要是用我之前<a href="http://blog.csdn.net/hejjunlin/article/details/52376462">《Android Multimedia框架总结（二）MediaPlayer框架及播放网络视频案例》</a>的例子，把直播地址，传给mediaplayer，就可以在手机上看直播了。</p><p>五、最后来张全家福，本地电脑和直播服务器同时看直播，有2-3秒延迟</p><p><img src="http://img.blog.csdn.net/20170507161647372?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqanVubGlu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>]]></content>
    
    
    <summary type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;/upload/FinalFantasy.jpg&quot; alt=&quot;这里写图片描述&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;一、下载 nginx 和 nginx-rtmp源码：&lt;br&gt;</summary>
    
    
    
    <category term="ffmpeg" scheme="https://www.stockclaw.asia/categories/ffmpeg/"/>
    
    
    <category term="ffmpeg" scheme="https://www.stockclaw.asia/tags/ffmpeg/"/>
    
    <category term="nginx" scheme="https://www.stockclaw.asia/tags/nginx/"/>
    
  </entry>
  
  <entry>
    <title>C++虚函数</title>
    <link href="https://www.stockclaw.asia/2017/06/23/C-%E8%99%9A%E5%87%BD%E6%95%B0/"/>
    <id>https://www.stockclaw.asia/2017/06/23/C-%E8%99%9A%E5%87%BD%E6%95%B0/</id>
    <published>2017-06-23T09:52:45.000Z</published>
    <updated>2019-03-31T13:58:22.000Z</updated>
    
    <content type="html"><![CDATA[<center><br><img src="/upload/game.jpg" alt="这里写图片描述"><br></center><p>为什么使用虚函数？什么是虚函数？虚函数是为了解决什么问题？<br><span id="more"></span><br>面向对象的三大特征：</p><ul><li>封装</li><li>多态</li><li><p>继承</p><ul><li>普通虚函数</li><li>虚析构函数</li><li>纯虚函数</li><li>抽象类</li><li>接口类</li><li>隐藏 vs 覆盖</li><li>隐藏与覆盖之间的关系</li><li>早绑定和晚绑定</li><li>虚函数表</li><li>什么是多态?</li></ul></li></ul><p>相同对象收到不同消息或不同对象收到相同消息时产生的不同的动作。</p><p>静态多态 vs 动态多态</p><p>[-:&gt;静态多态也叫做早绑定<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Rect</span>       <span class="comment">//矩形类</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">calcArea</span><span class="params">(<span class="type">int</span> width)</span></span>;</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">calcArea</span><span class="params">(<span class="type">int</span> width,<span class="type">int</span> height)</span></span>;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><br>如上面的代码，他们函数名相同，参数个数不同，一看就是互为重载的两个函数<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Rect.rect;</span><br><span class="line">    rect.<span class="built_in">calcArea</span>(<span class="number">10</span>);</span><br><span class="line">    rect.<span class="built_in">calcArea</span>(<span class="number">10</span>,<span class="number">20</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>程序在编译阶段根据参数个数确定调用哪个函数。这种情况叫做静态多态（早绑定）</p><p>[-:&gt;动态多态也叫做晚绑定</p><p>比如计算面积 当给圆形计算面积时使用圆形面积的计算公式，给矩形计算面积时使用矩形面积的计算公式。也就是说有一个计算面积的形状基类，圆形和矩形类派生自形状类，圆形与矩形的类各有自己的计算面积的方法。可见动态多态是以封装和继承为基础的。<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Shape</span><span class="comment">//形状类</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">double</span> <span class="title">calcArea</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout&lt;&lt;<span class="string">&quot;calcArea&quot;</span>&lt;&lt;endl;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;；</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Circle</span>:<span class="keyword">public</span> Shape      <span class="comment">//公有继承自形状类的圆形类</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Circle</span>(<span class="type">double</span> r);</span><br><span class="line">    <span class="function"><span class="type">double</span> <span class="title">calcArea</span><span class="params">()</span></span>;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">double</span> m_dR;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="type">double</span> <span class="title">Circle::calcArea</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">3.14</span>*m_dR*m_dR;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Rect</span>:<span class="keyword">public</span> Shape       <span class="comment">//公有继承自形状类的矩形类</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Rect</span>(<span class="type">double</span> width,<span class="type">double</span> height);</span><br><span class="line">    <span class="function"><span class="type">double</span> <span class="title">calArea</span><span class="params">()</span></span>;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">double</span> m_dWidth;</span><br><span class="line">    <span class="type">double</span> m_dHeight;</span><br><span class="line">&#125;；</span><br><span class="line"><span class="function"><span class="type">double</span> <span class="title">Rect::calcArea</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> m_dWidth*m_dHeight;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Shape *shape1=<span class="keyword">new</span> <span class="built_in">Circle</span>(<span class="number">4.0</span>);</span><br><span class="line">    Shape *shape2=<span class="keyword">new</span> <span class="built_in">Rect</span>(<span class="number">3.0</span>,<span class="number">5.0</span>);</span><br><span class="line">    shape1-&gt;<span class="built_in">calcArea</span>();</span><br><span class="line">    shape2-&gt;<span class="built_in">calcArea</span>();</span><br><span class="line">    .......</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>如果打印结果的话，以上程序结果会打印两行”calcArea”，因为调用到的都是父类的calcArea函数，并不是我们想要的那样去分别调用各自的计算面积的函数。如果要想实现动态多态则必须使用虚函数</p><p>关键字 virtual -&gt;虚函数</p><p>用virtual去修饰成员函数使其成为虚函数</p><p>所以以上函数的修改部分如下</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Shape</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">double</span> <span class="title">calcArea</span><span class="params">()</span></span>&#123;...&#125;<span class="comment">//虚函数</span></span><br><span class="line">    ....                                      <span class="comment">//其他部分</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    ....</span><br><span class="line">&#125;；</span><br><span class="line">....</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Circle</span>:<span class="keyword">public</span> Shape</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Circle</span>(<span class="type">double</span> r);</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">double</span> <span class="title">calcArea</span><span class="params">()</span></span>;<span class="comment">//此处的virtual不是必须的，如果不加，系统会自动加</span></span><br><span class="line">                                        <span class="comment">//上，如果加上则会在后续的时候看的比较明显（推荐加上）</span></span><br><span class="line">    ....</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    ....</span><br><span class="line">&#125;;</span><br><span class="line">....</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Rect</span>:<span class="keyword">public</span> Shape</span><br><span class="line">&#123;</span><br><span class="line">    <span class="built_in">Rect</span>(<span class="type">double</span> width,<span class="type">double</span> height);</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">double</span> <span class="title">calcArea</span><span class="params">()</span></span>;</span><br><span class="line"><span class="keyword">private</span></span><br><span class="line">    ....</span><br><span class="line">&#125;;</span><br><span class="line">....</span><br></pre></td></tr></table></figure><p>这样就可以达到预期的结果了</p><p>多态中存在的问题</p><p>[-:&gt;内存泄漏，一个很严重的问题</p><p>例如上面的程序中，如果在圆形的类中定义一个圆心的坐标，并且坐标是在堆中申请的内存，则在mian函数中通过父类指针操作子类对象的成员函数的时候是没有问题的，可是在销毁对象内存的时候则只是执行了父类的析构函数，子类的析构函数却没有执行，这会导致内存泄漏。部分代码如下(想去借助父类指针去销毁子类对象的时候去不能去销毁子类对象)</p><p>如果delete后边跟父类的指针则只会执行父类的析构函数，如果delete后面跟的是子类的指针，那么它即会执行子类的析构函数，也会执行父类的析构函数</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Circle</span>:<span class="keyword">public</span> Shape</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Circle</span>(<span class="type">int</span> x,<span class="type">int</span> y,<span class="type">double</span> r);</span><br><span class="line">    ~<span class="built_in">Circle</span>();</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">double</span> <span class="title">calcArea</span><span class="params">()</span></span>;</span><br><span class="line">    ....</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">double</span> m_dR;</span><br><span class="line">    Coordinate *m_pCenter;      <span class="comment">//坐标类指针</span></span><br><span class="line">    ....</span><br><span class="line">&#125;;</span><br><span class="line">Circle::<span class="built_in">Circle</span>(<span class="type">int</span> x,<span class="type">int</span> y,<span class="type">double</span> r)</span><br><span class="line">&#123;</span><br><span class="line">    m_pCenter=<span class="keyword">new</span> <span class="built_in">Coordinate</span>(x,y);</span><br><span class="line">    m_dR=r;</span><br><span class="line">&#125;</span><br><span class="line">Circle::~<span class="built_in">Circle</span>()</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">delete</span> m_pCenter;</span><br><span class="line">    m_pCenter-<span class="literal">NULL</span>;</span><br><span class="line">&#125;</span><br><span class="line">....</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Shape *shape1=<span class="keyword">new</span> <span class="built_in">Circle</span>(<span class="number">3</span>,<span class="number">5</span>,<span class="number">4.0</span>);</span><br><span class="line">    shape1-&gt;<span class="built_in">calcArea</span>();</span><br><span class="line">    <span class="keyword">delete</span> shape1;</span><br><span class="line">    shape1=<span class="literal">NULL</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可见我们必须要去解决这个问题，不解决这个问题当使用的时候都会造成内存泄漏。面对这种情况则需要引入虚析构函数</p><p>虚析构函数</p><p>关键字 virtual -&gt;析构函数</p><p>之前是使用virtual去修饰成员函数，这里使用virtual去修饰析构函数，部分代码如下</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Shape</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    ....</span><br><span class="line">    <span class="keyword">virtual</span> ~<span class="built_in">Shape</span>();</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    ....</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Circle</span>:<span class="keyword">public</span> Shape</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">virtual</span> ~<span class="built_in">Circle</span>();<span class="comment">//与虚函数相同，此处virtual可以不写，系统将会自动添加，建议写上</span></span><br><span class="line">    ....</span><br><span class="line">&#125;;</span><br><span class="line">....</span><br></pre></td></tr></table></figure><p>这样父类指针指向的是哪个对象，哪个对象的构造函数就会先执行，然后执行父类的构造函数。销毁的时候子类的析构函数也会执行。</p><p>virtual关键字可以修饰普通的成员函数，也可以修饰析构函数，但并不是没有限制</p><p>virtual在函数中的使用限制</p><p>普通函数不能是虚函数，也就是说这个函数必须是某一个类的成员函数，不可以是一个全局函数，否则会导致编译错误。<br>静态成员函数不能是虚函数 static成员函数是和类同生共处的，他不属于任何对象，使用virtual也将导致错误。<br>内联函数不能是虚函数 如果修饰内联函数 如果内联函数被virtual修饰，计算机会忽略inline使它变成存粹的虚函数。<br>构造函数不能是虚函数，否则会出现编译错误。<br>虚函数实现原理</p><p>【：-》首先：什么是函数指针？</p><p>　　指针指向对象称为对象指针，指针除了指向对象还可以指向函数，函数的本质就是一段二进制代码，我们可以通过指针指向这段代码的开头，计算机就会从这个开头一直往下执行，直到函数结束，并且通过指令返回回来。函数的指针与普通的指针本质上是一样的，也是由四个基本的内存单元组成，存储着内存的地址，这个地址就是函数的首地址。</p><p>【：-》多态的实现原理</p><p>虚函数表指针：类中除了定义的函数成员，还有一个成员是虚函数表指针（占四个基本内存单元），这个指针指向一个虚函数表的起始位置，这个表会与类的定义同时出现，这个表存放着该类的虚函数指针，调用的时候可以找到该类的虚函数表指针，通过虚函数表指针找到虚函数表，通过虚函数表的偏移找到函数的入口地址，从而找到要使用的虚函数。</p><p>当实例化一个该类的子类对象的时候，（如果）该类的子类并没有定义虚函数，但是却从父类中继承了虚函数，所以在实例化该类子类对象的时候也会产生一个虚函数表，这个虚函数表是子类的虚函数表，但是记录的子类的虚函数地址却是与父类的是一样的。所以通过子类对象的虚函数表指针找到自己的虚函数表，在自己的虚函数表找到的要执行的函数指针也是父类的相应函数入口的地址。</p><p>如果我们在子类中定义了从父类继承来的虚函数，对于父类来说情况是不变的，对于子类来说它的虚函数表与之前的虚函数表是一样的，但是此时子类定义了自己的（从父类那继承来的）相应函数，所以它的虚函数表当中管于这个函数的指针就会覆盖掉原有的指向父类函数的指针的值，换句话说就是指向了自己定义的相应函数，这样如果用父类的指针，指向子类的对象，就会通过子类对象当中的虚函数表指针找到子类的虚函数表，从而通过子类的虚函数表找到子类的相应虚函数地址，而此时的地址已经是该函数自己定义的虚函数入口地址，而不是父类的相应虚函数入口地址，所以执行的将会是子类当中的虚函数。这就是多态的原理。</p><p>函数的覆盖和隐藏</p><p>父类和子类出现同名函数称为隐藏。</p><p>父类对象.函数函数名(…);     //调用父类的函数<br>子类对象.函数名(…);           //调用子类的函数<br>子类对象.父类名::函数名(…);//子类调用从父类继承来的函数。<br>父类和子类出现同名虚函数称为覆盖</p><p>父类指针=new 子类名(…);父类指针-&gt;函数名(…);//调用子类的虚函数。<br>虚析构函数的实现原理</p><p>[:-&gt;虚析构函数的特点：</p><p>当我们在父类中通过virtual修饰析构函数之后，通过父类指针指向子类对象，通过delete接父类指针就可以释放掉子类对象<br>[:-&gt;理论前提：</p><p>执行完子类的析构函数就会执行父类的析构函数<br>原理：</p><p>如果父类当中定义了虚析构函数，那么父类的虚函数表当中就会有一个父类的虚析构函数的入口指针，指向的是父类的虚析构函数，子类虚函数表当中也会产生一个子类的虚析构函数的入口指针，指向的是子类的虚析构函数，这个时候使用父类的指针指向子类的对象，delete接父类指针，就会通过指向的子类的对象找到子类的虚函数表指针，从而找到虚函数表，再虚函数表中找到子类的虚析构函数，从而使得子类的析构函数得以执行，子类的析构函数执行之后系统会自动执行父类的虚析构函数。这个是虚析构函数的实现原理。</p><p>纯虚函数：</p><p>纯虚函数的定义</p><p>复制代码<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Shape</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span>  <span class="type">double</span> <span class="title">calcArea</span><span class="params">()</span><span class="comment">//虚函数</span></span></span><br><span class="line"><span class="function">    </span>&#123;....&#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span>  <span class="type">double</span> <span class="title">calcPerimeter</span><span class="params">()</span></span>=<span class="number">0</span>;<span class="comment">//纯虚函数</span></span><br><span class="line">    ....</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><br>复制代码<br>纯虚函数没有函数体，同时在定义的时候函数名后面要加“=0”。</p><p>纯虚函数的实现原理：</p><p>在虚函数原理的基础上，虚函数表中，虚函数的地址是一个有意义的值，如果是纯虚函数就实实在在的写一个0。</p><p>含有纯虚函数的类被称为抽象类</p><p>含有纯虚函数的类被称为抽象类，比如上面代码中的类就是一个抽象类，包含一个计算周长的纯虚函数。哪怕只有一个纯虚函数，那么这个类也是一个抽象类，纯虚函数没有函数体，所以抽象类不允许实例化对象，抽象类的子类也可以是一个抽象类。抽象类子类只有把抽象类当中的所有的纯虚函数都做了实现才可以实例化对象。</p><p>对于抽象的类来说，我们往往不希望它能实例化，因为实例化之后也没什么用，而对于一些具体的类来说，我们要求必须实现那些要求（纯虚函数），使之成为有具体动作的类。</p><p>近含有纯虚函数的类称为接口类</p><p>如果在抽象类当中仅含有纯虚函数而不含其他任何东西，我们称之为接口类。</p><p>没有任何数据成员<br>仅有成员函数<br>成员函数都是纯虚函数<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Shape</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">double</span> <span class="title">calcArea</span><span class="params">()</span></span>=<span class="number">0</span><span class="comment">//计算面积</span></span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">double</span> <span class="title">calcPerimeter</span><span class="params">()</span></span>=<span class="number">0</span><span class="comment">//计算周长</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><br>实际的工作中接口类更多的表达一种能力或协议</p><p>比如<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Flyable</span><span class="comment">//会飞</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">takeoff</span><span class="params">()</span></span>=<span class="number">0</span>;<span class="comment">//起飞</span></span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">land</span><span class="params">()</span></span>=<span class="number">0</span>;<span class="comment">//降落</span></span><br><span class="line">&#125;；</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Bird</span>:<span class="keyword">public</span> Flyable</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    ....</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">takeoff</span><span class="params">()</span></span>&#123;....&#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">land</span><span class="params">()</span></span>&#123;....&#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    ....</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">flyMatch</span><span class="params">(Flyable *a,Flyable *b)</span><span class="comment">//飞行比赛</span></span></span><br><span class="line"><span class="function"><span class="comment">//要求传入一个会飞对象的指针，此时鸟类的对象指针可以传入进来</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    ....</span><br><span class="line">    a-&gt;<span class="built_in">takeoff</span>();</span><br><span class="line">    b-&gt;<span class="built_in">takeoff</span>();</span><br><span class="line">    a-&gt;<span class="built_in">land</span>();</span><br><span class="line">    b-&gt;<span class="built_in">land</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>例如上面的代码，定义一个会飞的接口，凡是实现这个接口的都是会飞的，飞行比赛要求会飞的来参加，鸟实现了会飞的接口，所以鸟可以参加飞行比赛，如果复杂点定义一个能够射击的接口，那么实现射击接口的类就可以参加战争之类需要会射击的对象，有一个战斗机类通过多继承实现会飞的接口和射击的接口还可以参加空中作战的函数呢</p>]]></content>
    
    
    <summary type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;/upload/game.jpg&quot; alt=&quot;这里写图片描述&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;为什么使用虚函数？什么是虚函数？虚函数是为了解决什么问题？&lt;br&gt;</summary>
    
    
    
    <category term="C++" scheme="https://www.stockclaw.asia/categories/C/"/>
    
    
    <category term="虚函数" scheme="https://www.stockclaw.asia/tags/%E8%99%9A%E5%87%BD%E6%95%B0/"/>
    
  </entry>
  
  <entry>
    <title>Android Multimedia框架总结（二十八）NuPlayer到OMX过程</title>
    <link href="https://www.stockclaw.asia/2017/06/23/Android-Multimedia%E6%A1%86%E6%9E%B6%E6%80%BB%E7%BB%93%EF%BC%88%E4%BA%8C%E5%8D%81%E5%85%AB%EF%BC%89NuPlayer%E5%88%B0OMX%E8%BF%87%E7%A8%8B/"/>
    <id>https://www.stockclaw.asia/2017/06/23/Android-Multimedia%E6%A1%86%E6%9E%B6%E6%80%BB%E7%BB%93%EF%BC%88%E4%BA%8C%E5%8D%81%E5%85%AB%EF%BC%89NuPlayer%E5%88%B0OMX%E8%BF%87%E7%A8%8B/</id>
    <published>2017-06-23T09:36:06.000Z</published>
    <updated>2019-03-31T13:58:54.000Z</updated>
    
    <content type="html"><![CDATA[<center><br><img src="/upload/Knight.jpg" alt="这里写图片描述"><br></center><p>NuPlayer是谷歌新研发的。AwesomePlayer存在BUG，谷歌早已在android M版本中弃用。<br><span id="more"></span><br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">sp&lt;MediaPlayerBase&gt; MediaPlayerService::Client::<span class="built_in">createPlayer</span>(player_type playerType)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// determine if we have the right player type</span></span><br><span class="line">    sp&lt;MediaPlayerBase&gt; p = mPlayer;</span><br><span class="line">    <span class="keyword">if</span> ((p != <span class="literal">NULL</span>) &amp;&amp; (p-&gt;<span class="built_in">playerType</span>() != playerType)) &#123;</span><br><span class="line">        <span class="built_in">ALOGV</span>(<span class="string">&quot;delete player&quot;</span>);</span><br><span class="line">        p.<span class="built_in">clear</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (p == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        p = MediaPlayerFactory::<span class="built_in">createPlayer</span>(playerType, <span class="keyword">this</span>, notify, mPid);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (p != <span class="literal">NULL</span>) &#123;</span><br><span class="line">        p-&gt;<span class="built_in">setUID</span>(mUID);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> p;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>NuPlayerDriver构造时，new NuPlayer<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">NuPlayerDriver::<span class="built_in">NuPlayerDriver</span>()</span><br><span class="line">    : <span class="built_in">mState</span>(STATE_IDLE),</span><br><span class="line">      <span class="built_in">mIsAsyncPrepare</span>(<span class="literal">false</span>),</span><br><span class="line">      <span class="built_in">mAsyncResult</span>(UNKNOWN_ERROR),</span><br><span class="line">      <span class="built_in">mSetSurfaceInProgress</span>(<span class="literal">false</span>),</span><br><span class="line">      <span class="built_in">mDurationUs</span>(<span class="number">-1</span>),</span><br><span class="line">      <span class="built_in">mPositionUs</span>(<span class="number">-1</span>),</span><br><span class="line">      <span class="built_in">mNumFramesTotal</span>(<span class="number">0</span>),</span><br><span class="line">      <span class="built_in">mNumFramesDropped</span>(<span class="number">0</span>),</span><br><span class="line">      <span class="built_in">mLooper</span>(<span class="keyword">new</span> ALooper),</span><br><span class="line">      <span class="built_in">mPlayerFlags</span>(<span class="number">0</span>),</span><br><span class="line">      <span class="built_in">mAtEOS</span>(<span class="literal">false</span>),</span><br><span class="line">      <span class="built_in">mStartupSeekTimeUs</span>(<span class="number">-1</span>) &#123;</span><br><span class="line">    mLooper-&gt;<span class="built_in">setName</span>(<span class="string">&quot;NuPlayerDriver Looper&quot;</span>);</span><br><span class="line"></span><br><span class="line">    mLooper-&gt;<span class="built_in">start</span>(</span><br><span class="line">            <span class="literal">false</span>, <span class="comment">/* runOnCallingThread */</span></span><br><span class="line">            <span class="literal">true</span>,  <span class="comment">/* canCallJava */</span></span><br><span class="line">            PRIORITY_AUDIO);</span><br><span class="line"></span><br><span class="line">    mPlayer = <span class="keyword">new</span> NuPlayer;</span><br><span class="line">    mLooper-&gt;<span class="built_in">registerHandler</span>(mPlayer);</span><br><span class="line"></span><br><span class="line">    mPlayer-&gt;<span class="built_in">setDriver</span>(<span class="keyword">this</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>NuPlayer.h<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">NuPlayer</span> : <span class="keyword">public</span> AHandler &#123;</span><br><span class="line">    <span class="built_in">NuPlayer</span>(<span class="type">pid_t</span> pid);</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setUID</span><span class="params">(<span class="type">uid_t</span> uid)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setDriver</span><span class="params">(<span class="type">const</span> wp&lt;NuPlayerDriver&gt; &amp;driver)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setDataSourceAsync</span><span class="params">(<span class="type">const</span> sp&lt;IStreamSource&gt; &amp;source)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setDataSourceAsync</span><span class="params">(</span></span></span><br><span class="line"><span class="params"><span class="function">            <span class="type">const</span> sp&lt;IMediaHTTPService&gt; &amp;httpService,</span></span></span><br><span class="line"><span class="params"><span class="function">            <span class="type">const</span> <span class="type">char</span> *url,</span></span></span><br><span class="line"><span class="params"><span class="function">            <span class="type">const</span> KeyedVector&lt;String8, String8&gt; *headers)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setDataSourceAsync</span><span class="params">(<span class="type">int</span> fd, <span class="type">int64_t</span> offset, <span class="type">int64_t</span> length)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setDataSourceAsync</span><span class="params">(<span class="type">const</span> sp&lt;DataSource&gt; &amp;source)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">prepareAsync</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setVideoSurfaceTextureAsync</span><span class="params">(</span></span></span><br><span class="line"><span class="params"><span class="function">            <span class="type">const</span> sp&lt;IGraphicBufferProducer&gt; &amp;bufferProducer)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setAudioSink</span><span class="params">(<span class="type">const</span> sp&lt;MediaPlayerBase::AudioSink&gt; &amp;sink)</span></span>;</span><br><span class="line">    <span class="function"><span class="type">status_t</span> <span class="title">setPlaybackSettings</span><span class="params">(<span class="type">const</span> AudioPlaybackRate &amp;rate)</span></span>;</span><br><span class="line">    <span class="function"><span class="type">status_t</span> <span class="title">getPlaybackSettings</span><span class="params">(AudioPlaybackRate *rate <span class="comment">/* nonnull */</span>)</span></span>;</span><br><span class="line">    <span class="function"><span class="type">status_t</span> <span class="title">setSyncSettings</span><span class="params">(<span class="type">const</span> AVSyncSettings &amp;sync, <span class="type">float</span> videoFpsHint)</span></span>;</span><br><span class="line">    <span class="function"><span class="type">status_t</span> <span class="title">getSyncSettings</span><span class="params">(AVSyncSettings *sync <span class="comment">/* nonnull */</span>, <span class="type">float</span> *videoFps <span class="comment">/* nonnull */</span>)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">start</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">pause</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Will notify the driver through &quot;notifyResetComplete&quot; once finished.</span></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">resetAsync</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Will notify the driver through &quot;notifySeekComplete&quot; once finished</span></span><br><span class="line">    <span class="comment">// and needNotify is true.</span></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">seekToAsync</span><span class="params">(<span class="type">int64_t</span> seekTimeUs, <span class="type">bool</span> needNotify = <span class="literal">false</span>)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">status_t</span> <span class="title">setVideoScalingMode</span><span class="params">(<span class="type">int32_t</span> mode)</span></span>;</span><br><span class="line">    <span class="function"><span class="type">status_t</span> <span class="title">getTrackInfo</span><span class="params">(Parcel* reply)</span> <span class="type">const</span></span>;</span><br><span class="line">    <span class="function"><span class="type">status_t</span> <span class="title">getSelectedTrack</span><span class="params">(<span class="type">int32_t</span> type, Parcel* reply)</span> <span class="type">const</span></span>;</span><br><span class="line">    <span class="function"><span class="type">status_t</span> <span class="title">selectTrack</span><span class="params">(<span class="type">size_t</span> trackIndex, <span class="type">bool</span> select, <span class="type">int64_t</span> timeUs)</span></span>;</span><br><span class="line">    <span class="function"><span class="type">status_t</span> <span class="title">getCurrentPosition</span><span class="params">(<span class="type">int64_t</span> *mediaUs)</span></span>;</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">getStats</span><span class="params">(Vector&lt;sp&lt;AMessage&gt; &gt; *mTrackStats)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function">sp&lt;MetaData&gt; <span class="title">getFileMeta</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="type">float</span> <span class="title">getFrameRate</span><span class="params">()</span></span>;</span><br></pre></td></tr></table></figure></p><p>当调用setDataSource时，<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">NuPlayer::setDataSourceAsync</span><span class="params">(<span class="type">const</span> sp&lt;IStreamSource&gt; &amp;source)</span> </span>&#123;</span><br><span class="line">    sp&lt;AMessage&gt; msg = <span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatSetDataSource, <span class="keyword">this</span>);</span><br><span class="line"></span><br><span class="line">    sp&lt;AMessage&gt; notify = <span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatSourceNotify, <span class="keyword">this</span>);</span><br><span class="line"></span><br><span class="line">    msg-&gt;<span class="built_in">setObject</span>(<span class="string">&quot;source&quot;</span>, <span class="keyword">new</span> <span class="built_in">StreamingSource</span>(notify, source));</span><br><span class="line">    msg-&gt;<span class="built_in">post</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>当发送Message时<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">NuPlayer::onMessageReceived</span><span class="params">(<span class="type">const</span> sp&lt;AMessage&gt; &amp;msg)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">switch</span> (msg-&gt;<span class="built_in">what</span>()) &#123;</span><br><span class="line">        <span class="keyword">case</span> kWhatSetDataSource:</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">ALOGV</span>(<span class="string">&quot;kWhatSetDataSource&quot;</span>);</span><br><span class="line"></span><br><span class="line">            <span class="built_in">CHECK</span>(mSource == <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">            <span class="type">status_t</span> err = OK;</span><br><span class="line">            sp&lt;RefBase&gt; obj;</span><br><span class="line">            <span class="built_in">CHECK</span>(msg-&gt;<span class="built_in">findObject</span>(<span class="string">&quot;source&quot;</span>, &amp;obj));</span><br><span class="line">            <span class="keyword">if</span> (obj != <span class="literal">NULL</span>) &#123;</span><br><span class="line">                mSource = <span class="built_in">static_cast</span>&lt;Source *&gt;(obj.<span class="built_in">get</span>());</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                err = UNKNOWN_ERROR;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="built_in">CHECK</span>(mDriver != <span class="literal">NULL</span>);</span><br><span class="line">            sp&lt;NuPlayerDriver&gt; driver = mDriver.<span class="built_in">promote</span>();</span><br><span class="line">            <span class="keyword">if</span> (driver != <span class="literal">NULL</span>) &#123;</span><br><span class="line">                driver-&gt;<span class="built_in">notifySetDataSourceCompleted</span>(err);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>当setDataSource好了后，上层发送start开始播放流程以后，开始创建解码器<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">NuPlayer::start</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    (<span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatStart, <span class="keyword">this</span>))-&gt;<span class="built_in">post</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">NuPlayer::onMessageReceived</span><span class="params">(<span class="type">const</span> sp&lt;AMessage&gt; &amp;msg)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">switch</span> (msg-&gt;<span class="built_in">what</span>()) &#123;</span><br><span class="line">        <span class="keyword">case</span> kWhatStart:</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">ALOGV</span>(<span class="string">&quot;kWhatStart&quot;</span>);</span><br><span class="line">            <span class="keyword">if</span> (mStarted) &#123;</span><br><span class="line">                <span class="comment">// do not resume yet if the source is still buffering</span></span><br><span class="line">                <span class="keyword">if</span> (!mPausedForBuffering) &#123;</span><br><span class="line">                    <span class="built_in">onResume</span>();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="built_in">onStart</span>();</span><br><span class="line">            &#125;</span><br><span class="line">            mPausedByClient = <span class="literal">false</span>;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>接下来<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">NuPlayer::onStart</span><span class="params">(<span class="type">int64_t</span> startPositionUs)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (!mSourceStarted) &#123;</span><br><span class="line">        mSourceStarted = <span class="literal">true</span>;</span><br><span class="line">        mSource-&gt;<span class="built_in">start</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (startPositionUs &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="built_in">performSeek</span>(startPositionUs);</span><br><span class="line">        <span class="keyword">if</span> (mSource-&gt;<span class="built_in">getFormat</span>(<span class="literal">false</span> <span class="comment">/* audio */</span>) == <span class="literal">NULL</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    mOffloadAudio = <span class="literal">false</span>;</span><br><span class="line">    mAudioEOS = <span class="literal">false</span>;</span><br><span class="line">    mVideoEOS = <span class="literal">false</span>;</span><br><span class="line">    mStarted = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line">    <span class="type">uint32_t</span> flags = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (mSource-&gt;<span class="built_in">isRealTime</span>()) &#123;</span><br><span class="line">        flags |= Renderer::FLAG_REAL_TIME;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    sp&lt;MetaData&gt; audioMeta = mSource-&gt;<span class="built_in">getFormatMeta</span>(<span class="literal">true</span> <span class="comment">/* audio */</span>);</span><br><span class="line">    <span class="type">audio_stream_type_t</span> streamType = AUDIO_STREAM_MUSIC;</span><br><span class="line">    <span class="keyword">if</span> (mAudioSink != <span class="literal">NULL</span>) &#123;</span><br><span class="line">        streamType = mAudioSink-&gt;<span class="built_in">getAudioStreamType</span>();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    sp&lt;AMessage&gt; videoFormat = mSource-&gt;<span class="built_in">getFormat</span>(<span class="literal">false</span> <span class="comment">/* audio */</span>);</span><br><span class="line"></span><br><span class="line">    mOffloadAudio =</span><br><span class="line">        <span class="built_in">canOffloadStream</span>(audioMeta, (videoFormat != <span class="literal">NULL</span>), mSource-&gt;<span class="built_in">isStreaming</span>(), streamType);</span><br><span class="line">    <span class="keyword">if</span> (mOffloadAudio) &#123;</span><br><span class="line">        flags |= Renderer::FLAG_OFFLOAD_AUDIO;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    sp&lt;AMessage&gt; notify = <span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatRendererNotify, <span class="keyword">this</span>);</span><br><span class="line">    ++mRendererGeneration;</span><br><span class="line">    notify-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;generation&quot;</span>, mRendererGeneration);</span><br><span class="line">    mRenderer = <span class="keyword">new</span> <span class="built_in">Renderer</span>(mAudioSink, notify, flags);</span><br><span class="line">    mRendererLooper = <span class="keyword">new</span> ALooper;</span><br><span class="line">    mRendererLooper-&gt;<span class="built_in">setName</span>(<span class="string">&quot;NuPlayerRenderer&quot;</span>);</span><br><span class="line">    mRendererLooper-&gt;<span class="built_in">start</span>(<span class="literal">false</span>, <span class="literal">false</span>, ANDROID_PRIORITY_AUDIO);</span><br><span class="line">    mRendererLooper-&gt;<span class="built_in">registerHandler</span>(mRenderer);</span><br><span class="line"></span><br><span class="line">    <span class="type">status_t</span> err = mRenderer-&gt;<span class="built_in">setPlaybackSettings</span>(mPlaybackSettings);</span><br><span class="line">    <span class="keyword">if</span> (err != OK) &#123;</span><br><span class="line">        mSource-&gt;<span class="built_in">stop</span>();</span><br><span class="line">        mSourceStarted = <span class="literal">false</span>;</span><br><span class="line">        <span class="built_in">notifyListener</span>(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">float</span> rate = <span class="built_in">getFrameRate</span>();</span><br><span class="line">    <span class="keyword">if</span> (rate &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        mRenderer-&gt;<span class="built_in">setVideoFrameRate</span>(rate);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (mVideoDecoder != <span class="literal">NULL</span>) &#123;</span><br><span class="line">        mVideoDecoder-&gt;<span class="built_in">setRenderer</span>(mRenderer);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (mAudioDecoder != <span class="literal">NULL</span>) &#123;</span><br><span class="line">        mAudioDecoder-&gt;<span class="built_in">setRenderer</span>(mRenderer);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">postScanSources</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>在onStart函数最后，有一个postScanSources()；实现如下：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">NuPlayer::postScanSources</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (mScanSourcesPending) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    sp&lt;AMessage&gt; msg = <span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatScanSources, <span class="keyword">this</span>);</span><br><span class="line">    msg-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;generation&quot;</span>, mScanSourcesGeneration);</span><br><span class="line">    msg-&gt;<span class="built_in">post</span>();</span><br><span class="line"></span><br><span class="line">    mScanSourcesPending = <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>会发一个Message，key是kWhatScanSources：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">NuPlayer::onMessageReceived</span><span class="params">(<span class="type">const</span> sp&lt;AMessage&gt; &amp;msg)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">switch</span> (msg-&gt;<span class="built_in">what</span>()) &#123;</span><br><span class="line">        <span class="keyword">case</span> kWhatScanSources:</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="type">int32_t</span> generation;</span><br><span class="line">            <span class="built_in">CHECK</span>(msg-&gt;<span class="built_in">findInt32</span>(<span class="string">&quot;generation&quot;</span>, &amp;generation));</span><br><span class="line">            <span class="keyword">if</span> (generation != mScanSourcesGeneration) &#123;</span><br><span class="line">                <span class="comment">// Drop obsolete msg.</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            mScanSourcesPending = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">            <span class="built_in">ALOGV</span>(<span class="string">&quot;scanning sources haveAudio=%d, haveVideo=%d&quot;</span>,</span><br><span class="line">                 mAudioDecoder != <span class="literal">NULL</span>, mVideoDecoder != <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">            <span class="type">bool</span> mHadAnySourcesBefore =</span><br><span class="line">                (mAudioDecoder != <span class="literal">NULL</span>) || (mVideoDecoder != <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// initialize video before audio because successful initialization of</span></span><br><span class="line">            <span class="comment">// video may change deep buffer mode of audio.</span></span><br><span class="line">            <span class="keyword">if</span> (mSurface != <span class="literal">NULL</span>) &#123;</span><br><span class="line">                <span class="built_in">instantiateDecoder</span>(<span class="literal">false</span>, &amp;mVideoDecoder);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// Don&#x27;t try to re-open audio sink if there&#x27;s an existing decoder.</span></span><br><span class="line">            <span class="keyword">if</span> (mAudioSink != <span class="literal">NULL</span> &amp;&amp; mAudioDecoder == <span class="literal">NULL</span>) &#123;</span><br><span class="line">                <span class="built_in">instantiateDecoder</span>(<span class="literal">true</span>, &amp;mAudioDecoder);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (!mHadAnySourcesBefore</span><br><span class="line">                    &amp;&amp; (mAudioDecoder != <span class="literal">NULL</span> || mVideoDecoder != <span class="literal">NULL</span>)) &#123;</span><br><span class="line">                <span class="comment">// This is the first time we&#x27;ve found anything playable.</span></span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span> (mSourceFlags &amp; Source::FLAG_DYNAMIC_DURATION) &#123;</span><br><span class="line">                    <span class="built_in">schedulePollDuration</span>();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="type">status_t</span> err;</span><br><span class="line">            <span class="keyword">if</span> ((err = mSource-&gt;<span class="built_in">feedMoreTSData</span>()) != OK) &#123;</span><br><span class="line">                <span class="keyword">if</span> (mAudioDecoder == <span class="literal">NULL</span> &amp;&amp; mVideoDecoder == <span class="literal">NULL</span>) &#123;</span><br><span class="line">                    <span class="comment">// We&#x27;re not currently decoding anything (no audio or</span></span><br><span class="line">                    <span class="comment">// video tracks found) and we just ran out of input data.</span></span><br><span class="line"></span><br><span class="line">                    <span class="keyword">if</span> (err == ERROR_END_OF_STREAM) &#123;</span><br><span class="line">                        <span class="built_in">notifyListener</span>(MEDIA_PLAYBACK_COMPLETE, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        <span class="built_in">notifyListener</span>(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> ((mAudioDecoder == <span class="literal">NULL</span> &amp;&amp; mAudioSink != <span class="literal">NULL</span>)</span><br><span class="line">                    || (mVideoDecoder == <span class="literal">NULL</span> &amp;&amp; mSurface != <span class="literal">NULL</span>)) &#123;</span><br><span class="line">                msg-&gt;<span class="built_in">post</span>(<span class="number">100000ll</span>);</span><br><span class="line">                mScanSourcesPending = <span class="literal">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>先初始化视频解码器，再初始化音频解码器。最后都会进入到instantiateDecoder，<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">status_t</span> <span class="title">NuPlayer::instantiateDecoder</span><span class="params">(<span class="type">bool</span> audio, sp&lt;DecoderBase&gt; *decoder)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// The audio decoder could be cleared by tear down. If still in shut down</span></span><br><span class="line">    <span class="comment">// process, no need to create a new audio decoder.</span></span><br><span class="line">    <span class="keyword">if</span> (*decoder != <span class="literal">NULL</span> || (audio &amp;&amp; mFlushingAudio == SHUT_DOWN)) &#123;</span><br><span class="line">        <span class="keyword">return</span> OK;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    sp&lt;AMessage&gt; format = mSource-&gt;<span class="built_in">getFormat</span>(audio);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (format == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> -EWOULDBLOCK;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    format-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;priority&quot;</span>, <span class="number">0</span> <span class="comment">/* realtime */</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (!audio) &#123;</span><br><span class="line">        AString mime;</span><br><span class="line">        <span class="built_in">CHECK</span>(format-&gt;<span class="built_in">findString</span>(<span class="string">&quot;mime&quot;</span>, &amp;mime));</span><br><span class="line"></span><br><span class="line">        sp&lt;AMessage&gt; ccNotify = <span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatClosedCaptionNotify, <span class="keyword">this</span>);</span><br><span class="line">        <span class="keyword">if</span> (mCCDecoder == <span class="literal">NULL</span>) &#123;</span><br><span class="line">            mCCDecoder = <span class="keyword">new</span> <span class="built_in">CCDecoder</span>(ccNotify);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (mSourceFlags &amp; Source::FLAG_SECURE) &#123;</span><br><span class="line">            format-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;secure&quot;</span>, <span class="literal">true</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (mSourceFlags &amp; Source::FLAG_PROTECTED) &#123;</span><br><span class="line">            format-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;protected&quot;</span>, <span class="literal">true</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="type">float</span> rate = <span class="built_in">getFrameRate</span>();</span><br><span class="line">        <span class="keyword">if</span> (rate &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            format-&gt;<span class="built_in">setFloat</span>(<span class="string">&quot;operating-rate&quot;</span>, rate * mPlaybackSettings.mSpeed);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (audio) &#123;</span><br><span class="line">        sp&lt;AMessage&gt; notify = <span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatAudioNotify, <span class="keyword">this</span>);</span><br><span class="line">        ++mAudioDecoderGeneration;</span><br><span class="line">        notify-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;generation&quot;</span>, mAudioDecoderGeneration);</span><br><span class="line"></span><br><span class="line">        <span class="built_in">determineAudioModeChange</span>();</span><br><span class="line">        <span class="keyword">if</span> (mOffloadAudio) &#123;</span><br><span class="line">            <span class="type">const</span> <span class="type">bool</span> hasVideo = (mSource-&gt;<span class="built_in">getFormat</span>(<span class="literal">false</span> <span class="comment">/*audio */</span>) != <span class="literal">NULL</span>);</span><br><span class="line">            format-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;has-video&quot;</span>, hasVideo);</span><br><span class="line">            *decoder = <span class="keyword">new</span> <span class="built_in">DecoderPassThrough</span>(notify, mSource, mRenderer);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            *decoder = <span class="keyword">new</span> <span class="built_in">Decoder</span>(notify, mSource, mPID, mRenderer);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        sp&lt;AMessage&gt; notify = <span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatVideoNotify, <span class="keyword">this</span>);</span><br><span class="line">        ++mVideoDecoderGeneration;</span><br><span class="line">        notify-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;generation&quot;</span>, mVideoDecoderGeneration);</span><br><span class="line"></span><br><span class="line">        *decoder = <span class="keyword">new</span> <span class="built_in">Decoder</span>(</span><br><span class="line">                notify, mSource, mPID, mRenderer, mSurface, mCCDecoder);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// enable FRC if high-quality AV sync is requested, even if not</span></span><br><span class="line">        <span class="comment">// directly queuing to display, as this will even improve textureview</span></span><br><span class="line">        <span class="comment">// playback.</span></span><br><span class="line">        &#123;</span><br><span class="line">            <span class="type">char</span> value[PROPERTY_VALUE_MAX];</span><br><span class="line">            <span class="keyword">if</span> (<span class="built_in">property_get</span>(<span class="string">&quot;persist.sys.media.avsync&quot;</span>, value, <span class="literal">NULL</span>) &amp;&amp;</span><br><span class="line">                    (!<span class="built_in">strcmp</span>(<span class="string">&quot;1&quot;</span>, value) || !<span class="built_in">strcasecmp</span>(<span class="string">&quot;true&quot;</span>, value))) &#123;</span><br><span class="line">                format-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;auto-frc&quot;</span>, <span class="number">1</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    (*decoder)-&gt;<span class="built_in">init</span>();</span><br><span class="line">    (*decoder)-&gt;<span class="built_in">configure</span>(format);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// allocate buffers to decrypt widevine source buffers</span></span><br><span class="line">    <span class="keyword">if</span> (!audio &amp;&amp; (mSourceFlags &amp; Source::FLAG_SECURE)) &#123;</span><br><span class="line">        Vector&lt;sp&lt;ABuffer&gt; &gt; inputBufs;</span><br><span class="line">        <span class="built_in">CHECK_EQ</span>((*decoder)-&gt;<span class="built_in">getInputBuffers</span>(&amp;inputBufs), (<span class="type">status_t</span>)OK);</span><br><span class="line"></span><br><span class="line">        Vector&lt;MediaBuffer *&gt; mediaBufs;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">size_t</span> i = <span class="number">0</span>; i &lt; inputBufs.<span class="built_in">size</span>(); i++) &#123;</span><br><span class="line">            <span class="type">const</span> sp&lt;ABuffer&gt; &amp;buffer = inputBufs[i];</span><br><span class="line">            MediaBuffer *mbuf = <span class="keyword">new</span> <span class="built_in">MediaBuffer</span>(buffer-&gt;<span class="built_in">data</span>(), buffer-&gt;<span class="built_in">size</span>());</span><br><span class="line">            mediaBufs.<span class="built_in">push</span>(mbuf);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="type">status_t</span> err = mSource-&gt;<span class="built_in">setBuffers</span>(audio, mediaBufs);</span><br><span class="line">        <span class="keyword">if</span> (err != OK) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">size_t</span> i = <span class="number">0</span>; i &lt; mediaBufs.<span class="built_in">size</span>(); ++i) &#123;</span><br><span class="line">                mediaBufs[i]-&gt;<span class="built_in">release</span>();</span><br><span class="line">            &#125;</span><br><span class="line">            mediaBufs.<span class="built_in">clear</span>();</span><br><span class="line">            <span class="built_in">ALOGE</span>(<span class="string">&quot;Secure source didn&#x27;t support secure mediaBufs.&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span> err;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> OK;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><br> 开始<em>decoder = new Decoder(notify, mSource, mPID, mRenderer, mSurface, mCCDecoder); 然后(</em>decoder)-&gt;configure(format);这个Decoder结构体是定义在NuPlayerDecoder.h，看下对应configure实现。<br>在NuPlayerDecoder.cpp<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> NuPlayer::Decoder::<span class="built_in">onConfigure</span>(<span class="type">const</span> sp&lt;AMessage&gt; &amp;format) &#123;</span><br><span class="line">    <span class="built_in">CHECK</span>(mCodec == <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">    mFormatChangePending = <span class="literal">false</span>;</span><br><span class="line">    mTimeChangePending = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">    ++mBufferGeneration;</span><br><span class="line"></span><br><span class="line">    AString mime;</span><br><span class="line">    <span class="built_in">CHECK</span>(format-&gt;<span class="built_in">findString</span>(<span class="string">&quot;mime&quot;</span>, &amp;mime));</span><br><span class="line"></span><br><span class="line">    mIsAudio = !<span class="built_in">strncasecmp</span>(<span class="string">&quot;audio/&quot;</span>, mime.<span class="built_in">c_str</span>(), <span class="number">6</span>);</span><br><span class="line">    mIsVideoAVC = !<span class="built_in">strcasecmp</span>(MEDIA_MIMETYPE_VIDEO_AVC, mime.<span class="built_in">c_str</span>());</span><br><span class="line"></span><br><span class="line">    mComponentName = mime;</span><br><span class="line">    mComponentName.<span class="built_in">append</span>(<span class="string">&quot; decoder&quot;</span>);</span><br><span class="line">    <span class="built_in">ALOGV</span>(<span class="string">&quot;[%s] onConfigure (surface=%p)&quot;</span>, mComponentName.<span class="built_in">c_str</span>(), mSurface.<span class="built_in">get</span>());</span><br><span class="line"></span><br><span class="line">    mCodec = MediaCodec::<span class="built_in">CreateByType</span>(</span><br><span class="line">            mCodecLooper, mime.<span class="built_in">c_str</span>(), <span class="literal">false</span> <span class="comment">/* encoder */</span>, <span class="literal">NULL</span> <span class="comment">/* err */</span>, mPid);</span><br><span class="line">    <span class="type">int32_t</span> secure = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">if</span> (format-&gt;<span class="built_in">findInt32</span>(<span class="string">&quot;secure&quot;</span>, &amp;secure) &amp;&amp; secure != <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (mCodec != <span class="literal">NULL</span>) &#123;</span><br><span class="line">            mCodec-&gt;<span class="built_in">getName</span>(&amp;mComponentName);</span><br><span class="line">            mComponentName.<span class="built_in">append</span>(<span class="string">&quot;.secure&quot;</span>);</span><br><span class="line">            mCodec-&gt;<span class="built_in">release</span>();</span><br><span class="line">            <span class="built_in">ALOGI</span>(<span class="string">&quot;[%s] creating&quot;</span>, mComponentName.<span class="built_in">c_str</span>());</span><br><span class="line">            mCodec = MediaCodec::<span class="built_in">CreateByComponentName</span>(</span><br><span class="line">                    mCodecLooper, mComponentName.<span class="built_in">c_str</span>(), <span class="literal">NULL</span> <span class="comment">/* err */</span>, mPid);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (mCodec == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="built_in">ALOGE</span>(<span class="string">&quot;Failed to create %s%s decoder&quot;</span>,</span><br><span class="line">                (secure ? <span class="string">&quot;secure &quot;</span> : <span class="string">&quot;&quot;</span>), mime.<span class="built_in">c_str</span>());</span><br><span class="line">        <span class="built_in">handleError</span>(UNKNOWN_ERROR);</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    mIsSecure = secure;</span><br><span class="line"></span><br><span class="line">    mCodec-&gt;<span class="built_in">getName</span>(&amp;mComponentName);</span><br><span class="line"></span><br><span class="line">    <span class="type">status_t</span> err;</span><br><span class="line">    <span class="keyword">if</span> (mSurface != <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="comment">// disconnect from surface as MediaCodec will reconnect</span></span><br><span class="line">        err = <span class="built_in">native_window_api_disconnect</span>(</span><br><span class="line">                mSurface.<span class="built_in">get</span>(), NATIVE_WINDOW_API_MEDIA);</span><br><span class="line">        <span class="comment">// We treat this as a warning, as this is a preparatory step.</span></span><br><span class="line">        <span class="comment">// Codec will try to connect to the surface, which is where</span></span><br><span class="line">        <span class="comment">// any error signaling will occur.</span></span><br><span class="line">        <span class="built_in">ALOGW_IF</span>(err != OK, <span class="string">&quot;failed to disconnect from surface: %d&quot;</span>, err);</span><br><span class="line">    &#125;</span><br><span class="line">    err = mCodec-&gt;<span class="built_in">configure</span>(</span><br><span class="line">            format, mSurface, <span class="literal">NULL</span> <span class="comment">/* crypto */</span>, <span class="number">0</span> <span class="comment">/* flags */</span>);</span><br><span class="line">    <span class="keyword">if</span> (err != OK) &#123;</span><br><span class="line">        <span class="built_in">ALOGE</span>(<span class="string">&quot;Failed to configure %s decoder (err=%d)&quot;</span>, mComponentName.<span class="built_in">c_str</span>(), err);</span><br><span class="line">        mCodec-&gt;<span class="built_in">release</span>();</span><br><span class="line">        mCodec.<span class="built_in">clear</span>();</span><br><span class="line">        <span class="built_in">handleError</span>(err);</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">rememberCodecSpecificData</span>(format);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// the following should work in configured state</span></span><br><span class="line">    <span class="built_in">CHECK_EQ</span>((<span class="type">status_t</span>)OK, mCodec-&gt;<span class="built_in">getOutputFormat</span>(&amp;mOutputFormat));</span><br><span class="line">    <span class="built_in">CHECK_EQ</span>((<span class="type">status_t</span>)OK, mCodec-&gt;<span class="built_in">getInputFormat</span>(&amp;mInputFormat));</span><br><span class="line"></span><br><span class="line">    mStats-&gt;<span class="built_in">setString</span>(<span class="string">&quot;mime&quot;</span>, mime.<span class="built_in">c_str</span>());</span><br><span class="line">    mStats-&gt;<span class="built_in">setString</span>(<span class="string">&quot;component-name&quot;</span>, mComponentName.<span class="built_in">c_str</span>());</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (!mIsAudio) &#123;</span><br><span class="line">        <span class="type">int32_t</span> width, height;</span><br><span class="line">        <span class="keyword">if</span> (mOutputFormat-&gt;<span class="built_in">findInt32</span>(<span class="string">&quot;width&quot;</span>, &amp;width)</span><br><span class="line">                &amp;&amp; mOutputFormat-&gt;<span class="built_in">findInt32</span>(<span class="string">&quot;height&quot;</span>, &amp;height)) &#123;</span><br><span class="line">            mStats-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;width&quot;</span>, width);</span><br><span class="line">            mStats-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;height&quot;</span>, height);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    sp&lt;AMessage&gt; reply = <span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatCodecNotify, <span class="keyword">this</span>);</span><br><span class="line">    mCodec-&gt;<span class="built_in">setCallback</span>(reply);</span><br><span class="line"></span><br><span class="line">    err = mCodec-&gt;<span class="built_in">start</span>();</span><br><span class="line">    <span class="keyword">if</span> (err != OK) &#123;</span><br><span class="line">        <span class="built_in">ALOGE</span>(<span class="string">&quot;Failed to start %s decoder (err=%d)&quot;</span>, mComponentName.<span class="built_in">c_str</span>(), err);</span><br><span class="line">        mCodec-&gt;<span class="built_in">release</span>();</span><br><span class="line">        mCodec.<span class="built_in">clear</span>();</span><br><span class="line">        <span class="built_in">handleError</span>(err);</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">releaseAndResetMediaBuffers</span>();</span><br><span class="line"></span><br><span class="line">    mPaused = <span class="literal">false</span>;</span><br><span class="line">    mResumePending = <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>其中通过CreateByType创建MediaCodec，，位于MediaCodec.cpp<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// static</span></span><br><span class="line"><span class="function">sp&lt;MediaCodec&gt; <span class="title">MediaCodec::CreateByType</span><span class="params">(</span></span></span><br><span class="line"><span class="params"><span class="function">        <span class="type">const</span> sp&lt;ALooper&gt; &amp;looper, <span class="type">const</span> <span class="type">char</span> *mime, <span class="type">bool</span> encoder, <span class="type">status_t</span> *err, <span class="type">pid_t</span> pid)</span> </span>&#123;</span><br><span class="line">    sp&lt;MediaCodec&gt; codec = <span class="keyword">new</span> <span class="built_in">MediaCodec</span>(looper, pid);</span><br><span class="line"></span><br><span class="line">    <span class="type">const</span> <span class="type">status_t</span> ret = codec-&gt;<span class="built_in">init</span>(mime, <span class="literal">true</span> <span class="comment">/* nameIsType */</span>, encoder);</span><br><span class="line">    <span class="keyword">if</span> (err != <span class="literal">NULL</span>) &#123;</span><br><span class="line">        *err = ret;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> ret == OK ? codec : <span class="literal">NULL</span>; <span class="comment">// NULL deallocates codec.</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// static</span></span><br><span class="line"><span class="function">sp&lt;MediaCodec&gt; <span class="title">MediaCodec::CreateByComponentName</span><span class="params">(</span></span></span><br><span class="line"><span class="params"><span class="function">        <span class="type">const</span> sp&lt;ALooper&gt; &amp;looper, <span class="type">const</span> <span class="type">char</span> *name, <span class="type">status_t</span> *err, <span class="type">pid_t</span> pid)</span> </span>&#123;</span><br><span class="line">    sp&lt;MediaCodec&gt; codec = <span class="keyword">new</span> <span class="built_in">MediaCodec</span>(looper, pid);</span><br><span class="line"></span><br><span class="line">    <span class="type">const</span> <span class="type">status_t</span> ret = codec-&gt;<span class="built_in">init</span>(name, <span class="literal">false</span> <span class="comment">/* nameIsType */</span>, <span class="literal">false</span> <span class="comment">/* encoder */</span>);</span><br><span class="line">    <span class="keyword">if</span> (err != <span class="literal">NULL</span>) &#123;</span><br><span class="line">        *err = ret;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> ret == OK ? codec : <span class="literal">NULL</span>; <span class="comment">// NULL deallocates codec.</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>调用init函数，位于MediaCodec.cpp<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">status_t</span> <span class="title">MediaCodec::init</span><span class="params">(<span class="type">const</span> AString &amp;name, <span class="type">bool</span> nameIsType, <span class="type">bool</span> encoder)</span> </span>&#123;</span><br><span class="line">    mResourceManagerService-&gt;<span class="built_in">init</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// save init parameters for reset</span></span><br><span class="line">    mInitName = name;</span><br><span class="line">    mInitNameIsType = nameIsType;</span><br><span class="line">    mInitIsEncoder = encoder;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Current video decoders do not return from OMX_FillThisBuffer</span></span><br><span class="line">    <span class="comment">// quickly, violating the OpenMAX specs, until that is remedied</span></span><br><span class="line">    <span class="comment">// we need to invest in an extra looper to free the main event</span></span><br><span class="line">    <span class="comment">// queue.</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (nameIsType || !<span class="built_in">strncasecmp</span>(name.<span class="built_in">c_str</span>(), <span class="string">&quot;omx.&quot;</span>, <span class="number">4</span>)) &#123;</span><br><span class="line">        mCodec = <span class="keyword">new</span> ACodec;</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!nameIsType</span><br><span class="line">            &amp;&amp; !<span class="built_in">strncasecmp</span>(name.<span class="built_in">c_str</span>(), <span class="string">&quot;android.filter.&quot;</span>, <span class="number">15</span>)) &#123;</span><br><span class="line">        mCodec = <span class="keyword">new</span> MediaFilter;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> NAME_NOT_FOUND;</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">    </span><br><span class="line">    mLooper-&gt;<span class="built_in">registerHandler</span>(<span class="keyword">this</span>);</span><br><span class="line">    mCodec-&gt;<span class="built_in">setNotificationMessage</span>(<span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatCodecNotify, <span class="keyword">this</span>));</span><br><span class="line">    sp&lt;AMessage&gt; msg = <span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatInit, <span class="keyword">this</span>);</span><br></pre></td></tr></table></figure></p><p>MediaCodec.cpp中onMessageReceived函数<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">MediaCodec::onMessageReceived</span><span class="params">(<span class="type">const</span> sp&lt;AMessage&gt; &amp;msg)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">switch</span> (msg-&gt;<span class="built_in">what</span>()) &#123;</span><br><span class="line">    <span class="keyword">case</span> kWhatInit:</span><br><span class="line">        &#123;</span><br><span class="line">            sp&lt;AReplyToken&gt; replyID;</span><br><span class="line">            <span class="built_in">CHECK</span>(msg-&gt;<span class="built_in">senderAwaitsResponse</span>(&amp;replyID));</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (mState != UNINITIALIZED) &#123;</span><br><span class="line">                <span class="built_in">PostReplyWithError</span>(replyID, INVALID_OPERATION);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            mReplyID = replyID;</span><br><span class="line">            <span class="built_in">setState</span>(INITIALIZING);</span><br><span class="line"></span><br><span class="line">            AString name;</span><br><span class="line">            <span class="built_in">CHECK</span>(msg-&gt;<span class="built_in">findString</span>(<span class="string">&quot;name&quot;</span>, &amp;name));</span><br><span class="line"></span><br><span class="line">            <span class="type">int32_t</span> nameIsType;</span><br><span class="line">            <span class="type">int32_t</span> encoder = <span class="literal">false</span>;</span><br><span class="line">            <span class="built_in">CHECK</span>(msg-&gt;<span class="built_in">findInt32</span>(<span class="string">&quot;nameIsType&quot;</span>, &amp;nameIsType));</span><br><span class="line">            <span class="keyword">if</span> (nameIsType) &#123;</span><br><span class="line">                <span class="built_in">CHECK</span>(msg-&gt;<span class="built_in">findInt32</span>(<span class="string">&quot;encoder&quot;</span>, &amp;encoder));</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            sp&lt;AMessage&gt; format = <span class="keyword">new</span> AMessage;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (nameIsType) &#123;</span><br><span class="line">                format-&gt;<span class="built_in">setString</span>(<span class="string">&quot;mime&quot;</span>, name.<span class="built_in">c_str</span>());</span><br><span class="line">                format-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;encoder&quot;</span>, encoder);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                format-&gt;<span class="built_in">setString</span>(<span class="string">&quot;componentName&quot;</span>, name.<span class="built_in">c_str</span>());</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            mCodec-&gt;<span class="built_in">initiateAllocateComponent</span>(format);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>最后来到ACodec中，initiateAllocateComponent<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">ACodec::initiateAllocateComponent</span><span class="params">(<span class="type">const</span> sp&lt;AMessage&gt; &amp;msg)</span> </span>&#123;</span><br><span class="line">    msg-&gt;<span class="built_in">setWhat</span>(kWhatAllocateComponent);</span><br><span class="line">    msg-&gt;<span class="built_in">setTarget</span>(<span class="keyword">this</span>);</span><br><span class="line">    msg-&gt;<span class="built_in">post</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>消息接收<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">bool</span> ACodec::UninitializedState::<span class="built_in">onMessageReceived</span>(<span class="type">const</span> sp&lt;AMessage&gt; &amp;msg) &#123;</span><br><span class="line">    <span class="type">bool</span> handled = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">switch</span> (msg-&gt;<span class="built_in">what</span>()) &#123;</span><br><span class="line">        <span class="keyword">case</span> ACodec::kWhatSetup:</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">onSetup</span>(msg);</span><br><span class="line">            handled = <span class="literal">true</span>;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">case</span> ACodec::kWhatAllocateComponent:</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">onAllocateComponent</span>(msg);</span><br><span class="line">            handled = <span class="literal">true</span>;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>初始化组件<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">bool</span> ACodec::UninitializedState::<span class="built_in">onAllocateComponent</span>(<span class="type">const</span> sp&lt;AMessage&gt; &amp;msg) &#123;</span><br><span class="line">    <span class="built_in">ALOGV</span>(<span class="string">&quot;onAllocateComponent&quot;</span>);</span><br><span class="line">    <span class="built_in">CHECK</span>(mCodec-&gt;mNode == <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">    OMXClient client;</span><br><span class="line">    <span class="keyword">if</span> (client.<span class="built_in">connect</span>() != OK) &#123;</span><br><span class="line">        mCodec-&gt;<span class="built_in">signalError</span>(OMX_ErrorUndefined, NO_INIT);</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    sp&lt;IOMX&gt; omx = client.<span class="built_in">interface</span>();</span><br><span class="line"></span><br><span class="line">    sp&lt;AMessage&gt; notify = <span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatOMXDied, mCodec);</span><br><span class="line"></span><br><span class="line">    mDeathNotifier = <span class="keyword">new</span> <span class="built_in">DeathNotifier</span>(notify);</span><br><span class="line">    <span class="keyword">if</span> (IInterface::<span class="built_in">asBinder</span>(omx)-&gt;<span class="built_in">linkToDeath</span>(mDeathNotifier) != OK) &#123;</span><br><span class="line">        <span class="comment">// This was a local binder, if it dies so do we, we won&#x27;t care</span></span><br><span class="line">        <span class="comment">// about any notifications in the afterlife.</span></span><br><span class="line">        mDeathNotifier.<span class="built_in">clear</span>();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    Vector&lt;OMXCodec::CodecNameAndQuirks&gt; matchingCodecs;</span><br><span class="line"></span><br><span class="line">    AString mime;</span><br><span class="line"></span><br><span class="line">    AString componentName;</span><br><span class="line">    <span class="type">uint32_t</span> quirks = <span class="number">0</span>;</span><br><span class="line">    <span class="type">int32_t</span> encoder = <span class="literal">false</span>;</span><br><span class="line">    <span class="keyword">if</span> (msg-&gt;<span class="built_in">findString</span>(<span class="string">&quot;componentName&quot;</span>, &amp;componentName)) &#123;</span><br><span class="line">        <span class="type">ssize_t</span> index = matchingCodecs.<span class="built_in">add</span>();</span><br><span class="line">        OMXCodec::CodecNameAndQuirks *entry = &amp;matchingCodecs.<span class="built_in">editItemAt</span>(index);</span><br><span class="line">        entry-&gt;mName = <span class="built_in">String8</span>(componentName.<span class="built_in">c_str</span>());</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (!OMXCodec::<span class="built_in">findCodecQuirks</span>(</span><br><span class="line">                    componentName.<span class="built_in">c_str</span>(), &amp;entry-&gt;mQuirks)) &#123;</span><br><span class="line">            entry-&gt;mQuirks = <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="built_in">CHECK</span>(msg-&gt;<span class="built_in">findString</span>(<span class="string">&quot;mime&quot;</span>, &amp;mime));</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (!msg-&gt;<span class="built_in">findInt32</span>(<span class="string">&quot;encoder&quot;</span>, &amp;encoder)) &#123;</span><br><span class="line">            encoder = <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        OMXCodec::<span class="built_in">findMatchingCodecs</span>(</span><br><span class="line">                mime.<span class="built_in">c_str</span>(),</span><br><span class="line">                encoder, <span class="comment">// createEncoder</span></span><br><span class="line">                <span class="literal">NULL</span>,  <span class="comment">// matchComponentName</span></span><br><span class="line">                <span class="number">0</span>,     <span class="comment">// flags</span></span><br><span class="line">                &amp;matchingCodecs);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    sp&lt;CodecObserver&gt; observer = <span class="keyword">new</span> CodecObserver;</span><br><span class="line">    IOMX::node_id node = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="type">status_t</span> err = NAME_NOT_FOUND;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">size_t</span> matchIndex = <span class="number">0</span>; matchIndex &lt; matchingCodecs.<span class="built_in">size</span>();</span><br><span class="line">            ++matchIndex) &#123;</span><br><span class="line">        componentName = matchingCodecs.<span class="built_in">itemAt</span>(matchIndex).mName.<span class="built_in">string</span>();</span><br><span class="line">        quirks = matchingCodecs.<span class="built_in">itemAt</span>(matchIndex).mQuirks;</span><br><span class="line"></span><br><span class="line">        <span class="type">pid_t</span> tid = <span class="built_in">gettid</span>();</span><br><span class="line">        <span class="type">int</span> prevPriority = <span class="built_in">androidGetThreadPriority</span>(tid);</span><br><span class="line">        <span class="built_in">androidSetThreadPriority</span>(tid, ANDROID_PRIORITY_FOREGROUND);</span><br><span class="line">        err = omx-&gt;<span class="built_in">allocateNode</span>(componentName.<span class="built_in">c_str</span>(), observer, &amp;node);</span><br><span class="line">        <span class="built_in">androidSetThreadPriority</span>(tid, prevPriority);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (err == OK) &#123;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="built_in">ALOGW</span>(<span class="string">&quot;Allocating component &#x27;%s&#x27; failed, try next one.&quot;</span>, componentName.<span class="built_in">c_str</span>());</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        node = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (node == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (!mime.<span class="built_in">empty</span>()) &#123;</span><br><span class="line">            <span class="built_in">ALOGE</span>(<span class="string">&quot;Unable to instantiate a %scoder for type &#x27;%s&#x27; with err %#x.&quot;</span>,</span><br><span class="line">                    encoder ? <span class="string">&quot;en&quot;</span> : <span class="string">&quot;de&quot;</span>, mime.<span class="built_in">c_str</span>(), err);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="built_in">ALOGE</span>(<span class="string">&quot;Unable to instantiate codec &#x27;%s&#x27; with err %#x.&quot;</span>, componentName.<span class="built_in">c_str</span>(), err);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        mCodec-&gt;<span class="built_in">signalError</span>((OMX_ERRORTYPE)err, <span class="built_in">makeNoSideEffectStatus</span>(err));</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    notify = <span class="keyword">new</span> <span class="built_in">AMessage</span>(kWhatOMXMessageList, mCodec);</span><br><span class="line">    observer-&gt;<span class="built_in">setNotificationMessage</span>(notify);</span><br><span class="line"></span><br><span class="line">    mCodec-&gt;mComponentName = componentName;</span><br><span class="line">    mCodec-&gt;mRenderTracker.<span class="built_in">setComponentName</span>(componentName);</span><br><span class="line">    mCodec-&gt;mFlags = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (componentName.<span class="built_in">endsWith</span>(<span class="string">&quot;.secure&quot;</span>)) &#123;</span><br><span class="line">        mCodec-&gt;mFlags |= kFlagIsSecure;</span><br><span class="line">        mCodec-&gt;mFlags |= kFlagIsGrallocUsageProtected;</span><br><span class="line">        mCodec-&gt;mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    mCodec-&gt;mQuirks = quirks;</span><br><span class="line">    mCodec-&gt;mOMX = omx;</span><br><span class="line">    mCodec-&gt;mNode = node;</span><br><span class="line"></span><br><span class="line">    &#123;</span><br><span class="line">        sp&lt;AMessage&gt; notify = mCodec-&gt;mNotify-&gt;<span class="built_in">dup</span>();</span><br><span class="line">        notify-&gt;<span class="built_in">setInt32</span>(<span class="string">&quot;what&quot;</span>, CodecBase::kWhatComponentAllocated);</span><br><span class="line">        notify-&gt;<span class="built_in">setString</span>(<span class="string">&quot;componentName&quot;</span>, mCodec-&gt;mComponentName.<span class="built_in">c_str</span>());</span><br><span class="line">        notify-&gt;<span class="built_in">post</span>();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    mCodec-&gt;<span class="built_in">changeState</span>(mCodec-&gt;mLoadedState);</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>]]></content>
    
    
    <summary type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;/upload/Knight.jpg&quot; alt=&quot;这里写图片描述&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;NuPlayer是谷歌新研发的。AwesomePlayer存在BUG，谷歌早已在android M版本中弃用。&lt;br&gt;</summary>
    
    
    
    <category term="Android Multimedia" scheme="https://www.stockclaw.asia/categories/Android-Multimedia/"/>
    
    
    <category term="NuPlayer" scheme="https://www.stockclaw.asia/tags/NuPlayer/"/>
    
  </entry>
  
</feed>
