<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[【R128】基础组件开发指南——RTOS 多媒体解码]]></title><description><![CDATA[<p dir="auto">基于R128-S2设计的全套开发板已上线淘宝百问网韦东山老师个人店进行售卖，包含黑色的DshanMCU-R128s2-R16N16模组和全套的DshanMCU-R128s2-DEVKIT。</p>
<ul>
<li><strong>DshanMCU-R128s2-R16N16模组：39.9元</strong></li>
<li><strong>DshanMCU-R128s2-DEVKIT开发板：59.9元</strong></li>
</ul>
<p dir="auto"><strong>R128开发板购买链接：<a href="https://item.taobao.com/item.htm?spm=a21n57.1.0.0.46b0523cMfarLo&amp;id=736154682975&amp;ns=1&amp;abbucket=5#detail" target="_blank" rel="noopener noreferrer nofollow ugc">https://item.taobao.com/item.htm?spm=a21n57.1.0.0.46b0523cMfarLo&amp;id=736154682975&amp;ns=1&amp;abbucket=5#detail</a></strong></p>
<p dir="auto"><img src="/assets/uploads/files/1696746474623-%E4%B8%BB%E5%9B%BE_01-%E4%B8%BA%E6%99%BA%E8%83%BD%E5%AF%B9%E8%B1%A1-1.jpg" alt="“主图_01”为智能对象-1.jpg" class=" img-responsive img-markdown" /></p>
<h1>RTOS 多媒体解码</h1>
<p dir="auto">介绍 FreeRTOS 下如何使用 rtplayer 的接口来开发播放器应用程序，方便播放器开发人员快速正确地开发，以及播放器测试人员如何根据该文档对 rtplayer 播放器进行验证测试。</p>
<h3>rtplayer 状态图</h3>
<p dir="auto">这张状态转换图清晰地描述了 rtlayer 的各个状态，也列举了主要的方法的调用时序，每种方法只能在一些特定的状态下使用，否则会出错。另外，只有在 Prepared、Started、Paused、Play‑backCompleted 这四种状态下可以进行 seekTo() 操作，并且 seekTo() 之后，状态不变。</p>
<p dir="auto"><img src="/assets/uploads/files/1696904952755-image-20230512165957929.png" alt="image-20230512165957929.png" class=" img-responsive img-markdown" width="1162" height="748" /></p>
<h4>Idle 状态</h4>
<p dir="auto">Idle 状态：当调用 player_init() 创建一个 rtplayer 或者调用了其 reset() 方法时，rtplayer 处于 idle状态。</p>
<h4>Initialized 状态</h4>
<p dir="auto">这个状态比较简单，调用 setDateSource_url() 方法就进入 Initialized 状态，表示此时要播放的文件已经设置好了</p>
<h4>Preparing 状态</h4>
<p dir="auto">调用 prepare() 函数还没返回或者是调用 prepareAsync() 并且还没收到 RTPLAYER_NOTIFY_PREPARED 这个回调消息的时候就处于 Preparing 状态</p>
<h4>Prepared 状态</h4>
<p dir="auto">调用 prepare() 函数已经返回或者是调用 prepareAsync() 并且已经收到 RTPLAYER_NOTIFY_PREPARED 这个回调消息之后的状态就处于 Prepared 状态。在这个状态下说明所有的资源都已经就绪了，调用 start() 函数就可以播放了。</p>
<h4>Started 状态</h4>
<p dir="auto">rtplayer 一旦 prepare 完成，就可以调用 start() 方法，这样 rtplayer 就处于 Started 状态，这表明 rtplayer 正在播放文件过程中。可以使用 XPlayerIsPlaying() 测试 rtplayer 是否处于了 Started 状态。如果播放完毕，而又设置了循环播放，则 rtplayer 仍然会处于 Started 状态。</p>
<h4>Paused 状态</h4>
<p dir="auto">Started 状态下可以调用 pause_l() 方法暂停 rtplayer，从而进入 Paused 状态，rtplayer 暂停后再次调用 start() 则可以继续 TPlayer 的播放，转到 Started 状态。</p>
<h4>Stopped 状态</h4>
<p dir="auto">Started 或者 Paused 状态下均可调用 stop() 停止 rtplayer，而处于 Stop 状态的 rtplayer 要想重新播放，需要通过 prepareAsync() 和 prepare() 回到先前的 Prepared 状态重新开始才可以。</p>
<h4>PlaybackCompleted 状态</h4>
<p dir="auto">文件正常播放完毕，而又没有设置循环播放的话就进入该状态，并且会通过 RTPLAYER_NOTIFY_PLAYBACK_COMPLETE 这个消息回调给应用。此时可以调用 start() 方法重新从头播放文件，也可以 stop() 停止 rtplayer，或者也可以 seekTo() 来重新定位播放位置。</p>
<h4>Error 状态</h4>
<p dir="auto">由于某种原因 rtplayer 出现了错误，就会进入该状态，并且会通过 RTPLAYER_NOTIFY_MEDIA_ERROR 这个消息回调给应用。如果 rtplayer 进入了 Error 状态，可以通过调用 reset() 来恢复，使得 rtplayer 重新返回到 Idle 状态。</p>
<h4>End 状态</h4>
<p dir="auto">通过 plater_deinit() 的方法可以进入 End 状态，只要 rtplayer 不再被使用，就应当尽快将其 destroy 掉。</p>
<h2>rtplayer 层接口</h2>
<h3>创建一个 rtplayer</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">uint32_t player_init(void)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>无</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 rtplayer 的指针，失败返回 NULL</li>
</ul>
<h3>销毁一个 rtplayer</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">void player_deinit(void* handle)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>无</li>
</ul>
<h3>设置 rtplayer 的消息回调函数</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">void registerCallback(void* handle, void* userData, player_callback_t fn)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针</li>
<li>userData: 回调消息处理对象</li>
<li>fn: 回调消息处理函数指针，需要由应用实现</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>无</li>
</ul>
<blockquote>
<p dir="auto">创建完 rtplayer 播放器之后，就要调用该函数设置回调消息处理函数。</p>
</blockquote>
<h3>设置播放文件的 url</h3>
<p dir="auto">可以是本地文件也可以是网络源</p>
<p dir="auto">函数原型</p>
<pre><code class="language-c">status_t setDataSource_url(void* handle,void* userData, const char * url, int id)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针</li>
<li>userData: 回调消息处理对象</li>
<li>url: 需要播放的文件的 url</li>
<li>id: 回调时使用的播放索引, 为 0 即可</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1 或错误码</li>
</ul>
<h3>解析文件头部信息，获取元数据</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">status_t prepare(void* handle)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针;</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1 或错误码</li>
</ul>
<h3>异步解析文件头部信息，获取元数据</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">status_t prepareAsync(void* handle)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针;</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1</li>
</ul>
<blockquote>
<p dir="auto">该函数是非阻塞函数，需要等到 RTPLAYER_NOTIFY_P‑ REPARED 消息回调之后才能调 start() 函数进行播放，而且 start() 函数不能在回调函数中调用</p>
</blockquote>
<h3>开始播放</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">status_t start(void* handle)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针;</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1</li>
</ul>
<h3>暂停播放</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c"> status_t pause_l(void* handle)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针;</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1</li>
</ul>
<h3>停止播放</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c"> status_t stop(void* handle)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1</li>
</ul>
<h3>重置播放器</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">status_t reset(void* handle)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针;</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1</li>
</ul>
<blockquote>
<p dir="auto">在任何状态下都可以调用该函数，每次播放不同的音频之前，都需要调用该函数重置播放器，另外，一般收到 RTPLAYER_NOTIFY_MEDIA_ERROR 这个消息的时候，也需要通过调用该函数来重置播放器。但是不能在回调函数中调用该函数，否则会出现死锁</p>
</blockquote>
<h3>跳播</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">status_t seekTo(void* handle, int sec)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针</li>
<li>sec: 跳播的位置，单位是：s</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1</li>
</ul>
<h3>获取当前播放的位置</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">status_t getCurrentPosition(void* handle, int * sec)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针;</li>
<li>sec: 存放当前播放的位置值，单位：s</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1</li>
</ul>
<h3>获取播放的文件总时长</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">status_t getDuration(void* handle, int * sec)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针;</li>
<li>sec: 存储文件总时长，单位：s</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1</li>
</ul>
<blockquote>
<p dir="auto">需要在 prepared 状态之后才可以调用该函数</p>
</blockquote>
<h3>获取播放的文件信息</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">MediaInfo* getMediaInfo(void* handle)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针;</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1</li>
</ul>
<blockquote>
<p dir="auto">需要在 prepared 状态之后才可以调用该函数</p>
</blockquote>
<h3>设置循环播放模式</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">status_t setLooping(void* handle, int loop)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>handle: 通过 player_init() 函数创建的 rtplayer 指针;</li>
<li>loop:1 表示单曲循环，0 表示不会单曲循环</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1</li>
</ul>
<h2>XPlayer 层播放接口</h2>
<h3>创建一个 XPlayer</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">XPlayer* XPlayerCreate()
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>无</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功: XPlayer 指针; 失败: NULL</li>
</ul>
<h3>设置 XPlayer 的回调通知</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerSetNotifyCallback(XPlayer* p, XPlayerNotifyCallback notifier, void* pUserData)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>P：通过 XPlayerCreate 创建的 Xplayer 指针</li>
<li>notifier：回调通知</li>
<li>pUserData：应用程序传下来的自定义数据</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：XPlayer 指针；失败：NULL</li>
</ul>
<blockquote>
<p dir="auto">Xplayer 将接收来自下层的回调通知，进行相应的操作</p>
</blockquote>
<h3>创建指向音频播放设备管理模块的指针，用于播放音频</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">SoundCtrl* RTSoundDeviceCreate(int card)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>card:声卡序号0：default;1：sw:audio1;2:sw:audio2;3:sw:audio3;4:sw:audio4;5:sw:audio5</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：音频播放设备管理模块的指针；失败：NULL</li>
</ul>
<h3>创建指向音频播放设备管理模块的指针，用于播放音频</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerSetDataSourceUrl(XPlayer* p, const char* pUrl, void* httpService, const CdxKeyedVectorT* pHeaders)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>pUrl：url 地址</li>
<li>httpService：服务器信息</li>
<li>pHeaders：头文件信息</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>返回值: 成功：0；失败：‑1 或线程响应设置数据源命令的返回值或线程响应 xplayer prepare 命令的返回值</li>
</ul>
<blockquote>
<p dir="auto">调用说明: 发送 SetDataSource 命令，获取需要播放的音频数据内容</p>
</blockquote>
<h3>将 XPlayer 置为准备状态, 解析头部信息，获取元数据</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerPrepare(XPlayer* p)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 Xplayer 指针</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：线程响应异步 Prepare 命令的返回值；失败：NULL</li>
</ul>
<blockquote>
<p dir="auto">该函数是阻塞函数，调用完返回之后就进入了 Prepared 状态，此时可调 XPlayerStart() 函数进行播放</p>
</blockquote>
<h3>将 XPlayer 置为异步准备状态</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerPrepareAsync(XPlayer* p)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 XPlayer 指针</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：线程响应异步 Prepare 命令的返回值；失败：NULL</li>
</ul>
<blockquote>
<p dir="auto">网络播放源一般采用 PrepareAsync，而不是 Prepare 命令，PrepareAsync 命令的返回值为 0 时说明响应成功，播放器准备工作已经完成可以开始播放，为‑1 时说明响应失败</p>
</blockquote>
<h3>将 XPlayer 置为启动状态</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerStart(XPlayer* p)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 XPlayer 指针</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：线程响应 start 命令的返回值；失败：NULL</li>
</ul>
<blockquote>
<p dir="auto">Start 命令的返回值为 0 时说明响应成功，为‑1 时说明响应失败</p>
</blockquote>
<h3>将 XPlayer 置为暂停状态</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerPause(XPlayer* p)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 XPlayer 指针</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：线程响应 pause 命令的返回值；失败：NULL</li>
</ul>
<blockquote>
<p dir="auto">在 XPlayer 处于 start 状态时可调用此接口，Pause 命令的返回值为 0 时说明响应成功，为‑1 时说明响应失败</p>
</blockquote>
<h3>将 XPlayer 置为停止状态</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerStop(XPlayer* p)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 XPlayer 指针</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：返回 0；失败：返回‑1</li>
</ul>
<h3>重置 XPlayer</h3>
<p dir="auto">将相关变量复位，并销毁各模块，如音频解码模块、音频解码数据接收模块等</p>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerReset(XPlayer* p)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 XPlayer 指针</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：线程响应 Reset 命令的返回值；失败：NULL</li>
</ul>
<blockquote>
<p dir="auto">Reset 命令的返回值为 0 时说明响应成功，为‑1 时说明响应失败</p>
</blockquote>
<h3>获取节目时长</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerGetDuration(XPlayer* p, int *msec)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 Xplayer 指针</li>
<li>msec：保存节目时长</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：0；失败：‑1</li>
</ul>
<blockquote>
<p dir="auto">在 XPlayer 处于 PREPARED、STARTED、PAUSED、STOPPED 或 COMPLETE 状态下才可调用此接口，否则操作无效</p>
</blockquote>
<h3>Seek 到给定的时间点</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerSeekTo(XPlayer* p, int nSeekTimeMs)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 Xplayer 指针</li>
<li>nSeekTimeMs：跳转的时间点</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：线程响应 Seek 命令的返回值；失败：NULL</li>
</ul>
<blockquote>
<p dir="auto">如果跳转前播放处于暂停状态，则跳转后将保持在暂停状态</p>
</blockquote>
<h3>获取媒体文件的总时长</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerGetDuration(XPlayer* p, int *msec)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 XPlayer 指针</li>
<li>msec：保存媒体文件的总时长</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：0；失败：‑1</li>
</ul>
<blockquote>
<p dir="auto">需要在 prepared 状态之后才可以调用该函数</p>
</blockquote>
<h3>获取当前的播放时间点（即播放位置）</h3>
<p dir="auto">在 XPlayer 处于 PREPARED、STARTED、PAUSED、STOPPED 或 COMPLETE 状态下才可调用此接口，否则操作无效，在 complete 状态下，可能会调用 prepare 方法并更改媒体信息，获取的播放时间以 ms 为单位</p>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerGetCurrentPosition(XPlayer* p, int* msec)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 XPlayer 指针</li>
<li>msec：保存当前的播放时间</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功：0；失败：‑1</li>
</ul>
<h3>获取媒体信息</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">MediaInfo* XPlayerGetMediaInfo(XPlayer* p)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 XPlayer 指针</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>成功返回 0，失败返回‑1。如果失败，则 mediaInfo 指针为 NULL</li>
</ul>
<blockquote>
<p dir="auto">需要在 prepared 状态之后才可以调用该函数</p>
</blockquote>
<h3>设置循环播放模式</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerSetLooping(XPlayer* p, int loop)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 XPlayer 指针</li>
<li>loop: 1: 表示单曲循环模式；0：表示不会循环</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>无</li>
</ul>
<h3>查询是否正在播放</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">int XPlayerIsPlaying(XPlayer* p)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 XPlayer 指针</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>1：正在播放；0：未播放</li>
</ul>
<h3>销毁一个 XPlayer</h3>
<p dir="auto">函数原型</p>
<pre><code class="language-c">void XPlayerDestroy(XPlayer* p)
</code></pre>
<p dir="auto">参数：</p>
<ul>
<li>p：通过 XPlayerCreate 创建的 XPlayer 指针</li>
</ul>
<p dir="auto">返回值：</p>
<ul>
<li>无</li>
</ul>
<h2>播放器开发示例</h2>
<ol>
<li>player_init() 创建一个播放器</li>
<li>registerCallback()  设置消息回调函数</li>
<li>setDataSource_url() 设置 url</li>
<li>prepare() 或 prepareAsync()  解析头部信息，获取元数据，并根据元数据的信息初始化对应的解码器</li>
<li>start() 播放 (注: 如果是用 prepareAsync() 函数，则需要等到 RTPLAYER_NOTIFY_PREPARED 消息回调之后才可以调用 start() 函数进行播放)</li>
<li>如果需要跳播，则可以调用 seekTo() 函数</li>
<li>如果需要暂停，则调用 pause_l() 函数进行暂停</li>
<li>如果需要停止，则可以调用 stop() 或 reset() 函数进行停止 (注：建议用 reset() 函数进行停止，因为任何状态下都可以调用 reset() 函数)</li>
<li>如果需要播放下一个或其他的，则可以先调用 reset() 函数使播放器进入 idle 状态，然后再重复 (3)(4)(5) 的步骤</li>
</ol>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdint.h&gt;
#include &lt;FreeRTOS.h&gt;
#include &lt;task.h&gt;
#include &lt;portable.h&gt;
#include &lt;string.h&gt;
#include &lt;console.h&gt;
#include &lt;semaphore.h&gt;
#include &lt;pthread.h&gt;
#include &lt;unistd.h&gt;
#include &lt;mqueue.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;stdlib.h&gt;
#include "FreeRTOS_POSIX/utils.h"
#include "rtplayer.h"
#include "xplayer.h"

#define PAUSE_CMD           'P'
#define PING_CMD            'p'
#define STOP_CMD            'S'
#define SEEK_TO_CMD         's'
#define SEEK_TO_CMD2        'j'
#define BACKGROUND_CMD      'b'
#define SHOW_BUFFER_CMD     'B'
#define QUIT_CMD            'q'
#define LOOP_CMD            'l'
#define GET_DURATION_CMD    'G'
#define GET_POSITION_CMD    'g'
#define HELP_CMD            'h'
#define INFO_CMD            'i'
#define REPLAY_CMD          'r'
#define RETRY_CMD           256

#define USE_PREPARE_ASYNC 0

#define LOGD(msg, arg...)      //printf("[PLAYER_DBG] &lt;%s : %d&gt; " msg "\n", __func__, __LINE__, ##arg)
#define LOGI(msg, arg...)      //printf("[PLAYER_INFO] &lt;%s : %d&gt; " msg "\n", __func__, __LINE__, ##arg)
#define LOGW(msg, arg...)      printf("[PLAYER_WRN] &lt;%s : %d&gt; " msg "\n", __func__, __LINE__, ##arg)
#define LOGE(msg, arg...)      printf("[PLAYER_ERR] &lt;%s : %d&gt; " msg "\n", __func__, __LINE__, ##arg)
typedef struct DemoPlayerContext
{
    RTPlayer* mRTplayer;
    sem_t mPreparedSem;
    mqd_t mRTplayerMq;
    pthread_t mThreadId;
    char *pUrl;
    int mSeekable;
    char isPlayingFlag;
    char mError;
    int inputMode;
    int isSetLoop;
    char quitFlag;//no_shell_input mode quitFlag
    int testMode;
    MediaInfo* mMediaInfo;
    int SoundCard;
}DemoPlayerContext;

typedef struct DemoPlayerMsg
{
    int msg;
    int data;
}DemoPlayerMsg;

#define INVALID_MQD     ( ( mqd_t ) -1 )
#define DEFAULT_MODE    0600
static const char *pcRTplayerMqName = "/rtplayerMq";
static volatile mqd_t mRTplayerMq = INVALID_MQD;
static int mRTplayerUserInput = 0;
static struct mq_attr xRTplayerMqAttr =
    {
        .mq_flags   =   0,
        .mq_maxmsg  =   3,
        .mq_msgsize =   sizeof(DemoPlayerMsg),
        .mq_curmsgs =   0
    };

static void showHelp(){
    printf("\n");
    printf("**************************\n");
    printf("* This is a simple audio player, when it is started, you can input commands to tell\n");
    printf("* what you want it to do.\n");
    printf("* Usage: \n");
    printf("*   tplayer_demo /data/test.mp3  : this means play test.mp3\n");
    printf("*   P  :this will Pause if in playing status,or Play in paused status \n");
    printf("*   S  :this means Stop \n");
    printf("*   s  :this means seek to 10s \n");
    printf("*   B  :show buffer \n");
    printf("*   b  :this means player will run in the background \n");
    printf("*   q  :this means quit the player \n");
    printf("*   l  :this means loop play \n");
    printf("*   G :this means Get  duration \n");
    printf("*   g :this means get  position \n");
    printf("*   i :this means show media info \n");
    printf("*   h :this means show the help information \n");
    printf("*   r : replay the current audio\n");
    printf("**************************\n");
}
static int rtplayer_clear_cmd(mqd_t mq){
    struct timespec cur, delay, abstime;
    clock_gettime( CLOCK_REALTIME, &amp;cur );
    delay.tv_sec = 0;
    delay.tv_nsec = 5*1000*1000;
    UTILS_TimespecAdd(&amp;cur, &amp;delay, &amp;abstime);
    DemoPlayerMsg msg;
    while(mq_timedreceive(mq, (char *)&amp;msg, sizeof(msg), NULL, &amp;abstime)!=-1);
    return 0;
}
static int rtplayer_send_cmd(mqd_t mq, int msg, int data){
    DemoPlayerMsg pmsg = {msg, data};
    struct timespec tsn, ts;
    clock_gettime(CLOCK_REALTIME, &amp;tsn);
    UTILS_TimespecAddNanoseconds(&amp;tsn, 20*1000*1000, &amp;ts);
    int status = mq_timedsend(mq, (char *)&amp;pmsg, sizeof(pmsg), 0, &amp;ts);
    if(status)
        LOGE("send cmd %c,%d failed!", pmsg.msg, pmsg.data);
    return status;
}

static int rtplayer_send_cmd_force(mqd_t mq, int msg, int data){
    int try_times = 0;
    DemoPlayerMsg pmsg = {msg, data};
    struct timespec tsn, ts;
    int status;
try_send:
    clock_gettime(CLOCK_REALTIME, &amp;tsn);
    UTILS_TimespecAddNanoseconds(&amp;tsn, 20*1000*1000, &amp;ts);
    status = mq_timedsend(mq, (char *)&amp;pmsg, sizeof(pmsg), 0, &amp;ts);
    if(status){
        try_times++;
        if(try_times&lt;5){
            LOGE("send cmd %c,%d failed, retry...", pmsg.msg, pmsg.data);
            goto try_send;
        }
        else if(try_times&lt;10){
            DemoPlayerMsg tmp;
            LOGE("send cmd %c,%d failed, retry...", pmsg.msg, pmsg.data);
            clock_gettime(CLOCK_REALTIME, &amp;tsn);
            UTILS_TimespecAddNanoseconds(&amp;tsn, 20*1000*1000, &amp;ts);
            status = mq_timedreceive(mq, (char *)&amp;tmp, sizeof(tmp), NULL, &amp;ts);
            if(status&lt;0){
                LOGE("mq_receive fail %d", status);
                goto fail_exit;
            }
            LOGW("drop: %c, %d", tmp.msg, tmp.data);
            goto try_send;
        }
        goto fail_exit;
    }
    return status;
fail_exit:
    LOGE("send cmd %c,%d failed!\n", pmsg.msg, pmsg.data);
    return status;
}

static void callbackFromRTplayer(void* userData,int msg, int id, int ext1, int ext2);
static void* RTplayerThread(void* arg){
    DemoPlayerContext* demoPlayer = (DemoPlayerContext*)arg;
    char quitFlag = 0;

    if(demoPlayer-&gt;inputMode)
    {
	while(1)
	{
	     if(demoPlayer-&gt;quitFlag)
	     {
		if(demoPlayer-&gt;mRTplayer != NULL)
		{
			printf("player finsh, quit the rtplayer\n");
			mRTplayerMq = INVALID_MQD;
#if USE_PREPARE_ASYNC
			sem_destroy(&amp;demoPlayer-&gt;mPreparedSem);
#endif
			player_deinit(demoPlayer-&gt;mRTplayer);
			free(demoPlayer-&gt;pUrl);
			free(demoPlayer);
		}
		break;
	     }
		usleep(50*1000);
	}
	return NULL;

    }
    while(!quitFlag){
        int cRxed = 0;
        int data = 0;
        DemoPlayerMsg msg;
        ssize_t status;
        if(demoPlayer-&gt;mRTplayerMq!=INVALID_MQD){
            usleep(50*1000);
            ssize_t status = mq_receive(demoPlayer-&gt;mRTplayerMq, (char *)&amp;msg, sizeof(msg), NULL);
            if(status&lt;=-1){
                LOGE("mq_receive fail %d", status);
                usleep(1*1000*1000);
                continue;
            }
            printf("receive %c,%d\n", msg.msg, msg.data);
            cRxed = msg.msg;
            data = msg.data;
        }
        else{
            cRxed = QUIT_CMD;
        }
        switch(cRxed){
            case PAUSE_CMD:
            {
                if(demoPlayer-&gt;isPlayingFlag){
                    printf("pause the rtplayer\n");
                    pause_l(demoPlayer-&gt;mRTplayer);
                    demoPlayer-&gt;isPlayingFlag = 0;
                }else{
                    printf("play the rtplayer\n");
                    start(demoPlayer-&gt;mRTplayer);
                    demoPlayer-&gt;isPlayingFlag = 1;
                }
                break;
            }
            case STOP_CMD:
            {
                printf("stop the rtplayer\n");
                stop(demoPlayer-&gt;mRTplayer);
                demoPlayer-&gt;isPlayingFlag = 0;
                break;
            }
            case SEEK_TO_CMD:
            {
                printf("rtplayer seek to 10 second\n");
                seekTo(demoPlayer-&gt;mRTplayer,10);
                break;
            }
            case SEEK_TO_CMD2:
            {
                printf("rtplayer seek to %d second\n", data);
                seekTo(demoPlayer-&gt;mRTplayer,data);
                break;
            }
            case QUIT_CMD:
            {
                printf("quit the rtplayer\n");
                mRTplayerMq = INVALID_MQD;
                //mq_close(demoPlayer-&gt;mRTplayerMq);
#if USE_PREPARE_ASYNC
                sem_destroy(&amp;demoPlayer-&gt;mPreparedSem);
#endif
                player_deinit(demoPlayer-&gt;mRTplayer);
                free(demoPlayer-&gt;pUrl);
                free(demoPlayer);
                quitFlag = 1;
                break;
            }
            case LOOP_CMD:
            {
                printf("let the rtplayer loop play\n");
                demoPlayer-&gt;isSetLoop = 1;
                setLooping(demoPlayer-&gt;mRTplayer,1);
                break;
            }
            case GET_DURATION_CMD:
            {
                printf("get the audio duration\n");
                int duration;
                getDuration(demoPlayer-&gt;mRTplayer,&amp;duration);
                printf("duration:%d s\n",duration);
                break;
            }
            case GET_POSITION_CMD:
            {
                printf("get the current position\n");
                int position;
                getCurrentPosition(demoPlayer-&gt;mRTplayer,&amp;position);
                printf("current position:%d s\n",position);
                break;
            }
            case HELP_CMD:
            {
                printf("show the help information\n");
                showHelp();
                break;
            }
	    case INFO_CMD:
	    {
		printf("**************************\n");
		printf("* show media information:\n");
		MediaInfo* mi = NULL;
		demoPlayer-&gt;mMediaInfo = getMediaInfo(demoPlayer-&gt;mRTplayer);
		if(demoPlayer-&gt;mMediaInfo != NULL){
                        mi = demoPlayer-&gt;mMediaInfo;
                        printf("* file size = %lld KB\n",mi-&gt;nFileSize/1024);
                        printf("* duration = %lld ms\n",mi-&gt;nDurationMs);
                        printf("* bitrate = %d Kbps\n",mi-&gt;nBitrate/1024);
                        printf("* container type = %d\n",mi-&gt;eContainerType);
                        printf("* audio stream num = %d\n",mi-&gt;nAudioStreamNum);
                        if(mi-&gt;pAudioStreamInfo != NULL){
                            printf("* audio codec tpye = %d\n",mi-&gt;pAudioStreamInfo-&gt;eCodecFormat);
                            printf("* audio channel num = %d\n",mi-&gt;pAudioStreamInfo-&gt;nChannelNum);
                            printf("* audio BitsPerSample = %d\n",mi-&gt;pAudioStreamInfo-&gt;nBitsPerSample);
                            printf("* audio sample rate  = %d\n",mi-&gt;pAudioStreamInfo-&gt;nSampleRate);
                        }
		printf("**************************\n");
                    }
                    break;

	    }
	    case SHOW_BUFFER_CMD:
	    {
		printf("**************************\n");
		printf("* show buffer information:\n");
		player_show_buffer();
		printf("**************************\n");
		break;

	    }
            case REPLAY_CMD:
            {
                printf("replay %s\n", demoPlayer-&gt;pUrl);
                int ret;
                if(demoPlayer-&gt;testMode){
                    printf("test mode: destroy &amp; create instead of reset\n");
                    player_deinit(demoPlayer-&gt;mRTplayer);
                    usleep(50*1000);
                    demoPlayer-&gt;mRTplayer = (RTPlayer*)(uintptr_t)player_init();
                    printf("demoPlayer.mRTplayer = %p\n",demoPlayer-&gt;mRTplayer);
                    if(!demoPlayer-&gt;mRTplayer){
                        printf("init rtplayer fail\n");
                        free(demoPlayer-&gt;pUrl);
                        free(demoPlayer);
                        quitFlag = 1;
                        continue;
                    }
                    registerCallback(demoPlayer-&gt;mRTplayer, demoPlayer, callbackFromRTplayer);
                }
                else
                    reset(demoPlayer-&gt;mRTplayer);
                ret = setDataSource_url(demoPlayer-&gt;mRTplayer, demoPlayer, demoPlayer-&gt;pUrl, 0);
                if(ret){
                    printf("setDataSource_url failed\n");
                    break;
                }
                ret = prepare(demoPlayer-&gt;mRTplayer);
                if(ret){
                    printf("prepare failed\n");
                    break;
                }
                start(demoPlayer-&gt;mRTplayer);
                demoPlayer-&gt;isPlayingFlag = 1;
		if(demoPlayer-&gt;isSetLoop)
		{
                    setLooping(demoPlayer-&gt;mRTplayer,1);
		}
                break;
            }
            case RETRY_CMD:
            {
                int position = data;
                if(data==-1)
                    getCurrentPosition(demoPlayer-&gt;mRTplayer,&amp;position);
                printf("retry %s\n", demoPlayer-&gt;pUrl);
                int ret;
                if(demoPlayer-&gt;testMode){
                    printf("test mode: destroy &amp; create instead of reset\n");
                    player_deinit(demoPlayer-&gt;mRTplayer);
                    usleep(50*1000);
                    demoPlayer-&gt;mRTplayer = (RTPlayer*)(uintptr_t)player_init();
                    printf("demoPlayer.mRTplayer = %p\n",demoPlayer-&gt;mRTplayer);
                    if(!demoPlayer-&gt;mRTplayer){
                        LOGE("init rtplayer fail");
                        free(demoPlayer-&gt;pUrl);
                        free(demoPlayer);
                        quitFlag = 1;
                        continue;
                    }
                    registerCallback(demoPlayer-&gt;mRTplayer, demoPlayer, callbackFromRTplayer);
                }
                else
                    reset(demoPlayer-&gt;mRTplayer);
                ret = setDataSource_url(demoPlayer-&gt;mRTplayer, demoPlayer, demoPlayer-&gt;pUrl, 0);
                if(ret){
                    LOGE("setDataSource_url failed");
                    rtplayer_send_cmd_force(demoPlayer-&gt;mRTplayerMq, RETRY_CMD, position);
                    usleep(500*1000);
                    break;
                }
                ret = prepare(demoPlayer-&gt;mRTplayer);
                if(ret){
                    LOGE("prepare failed");
                    rtplayer_send_cmd_force(demoPlayer-&gt;mRTplayerMq, RETRY_CMD, position);
                    usleep(500*1000);
                    break;
                }
                start(demoPlayer-&gt;mRTplayer);
                demoPlayer-&gt;isPlayingFlag = 1;
                //seekTo(demoPlayer-&gt;mRTplayer, position);
                if(demoPlayer-&gt;isSetLoop)
                    setLooping(demoPlayer-&gt;mRTplayer,1);
                break;
            }
            default:
            {
                LOGW("warning: unknown command,cmd = %d",cRxed);
                break;
            }
        }
        if(quitFlag){
            return NULL;
        }
    }
    return NULL;
}
static void callbackFromRTplayer(void* userData,int msg, int id, int ext1, int ext2){

    LOGI("call back from RTplayer,msg = %d,id = %d,ext1 = %d,ext2 = %d\n",msg,id,ext1,ext2);

	DemoPlayerContext* pDemoPlayer = (DemoPlayerContext*)userData;
    switch(msg)
    {
        case RTPLAYER_NOTIFY_PREPARED:
        {
            printf("RTPLAYER_NOTIFY_PREPARED:has prepared.\n");
 #if USE_PREPARE_ASYNC           
            sem_post(&amp;pDemoPlayer-&gt;mPreparedSem);
            pDemoPlayer-&gt;mPreparedFlag = 1;
 #endif
            break;
        }
        case RTPLAYER_NOTIFY_PLAYBACK_COMPLETE:
        {
            printf("RTPLAYER_NOTIFY_PLAYBACK_COMPLETE:play complete\n");
            pDemoPlayer-&gt;isPlayingFlag = 0;
	    if(pDemoPlayer-&gt;inputMode)
	    {
		pDemoPlayer-&gt;quitFlag = 1;
	    }
            break;
        }
        case RTPLAYER_NOTIFY_SEEK_COMPLETE:
        {
            printf("RTPLAYER_NOTIFY_SEEK_COMPLETE:seek ok\n");
            break;
        }
        case RTPLAYER_NOTIFY_MEDIA_ERROR:
        {
            switch (ext1)
            {
                case RTPLAYER_MEDIA_ERROR_UNKNOWN:
                {
                    printf("erro type:TPLAYER_MEDIA_ERROR_UNKNOWN\n");
                    break;
                }
                case RTPLAYER_MEDIA_ERROR_UNSUPPORTED:
                {
                    printf("erro type:TPLAYER_MEDIA_ERROR_UNSUPPORTED\n");
                    break;
                }
                case RTPLAYER_MEDIA_ERROR_IO:
                {
                    printf("erro type:TPLAYER_MEDIA_ERROR_IO\n");
                    break;
                }
            }
            printf("RTPLAYER_NOTIFY_MEDIA_ERROR\n");
            pDemoPlayer-&gt;mError = 1;
#if USE_PREPARE_ASYNC            
            if(pDemoPlayer-&gt;mPreparedFlag == 0){
                printf("recive err when preparing\n");
                sem_post(&amp;pDemoPlayer-&gt;mPreparedSem);
            }
#endif 
            if( pDemoPlayer-&gt;mRTplayerMq!=INVALID_MQD ){
                rtplayer_send_cmd_force(pDemoPlayer-&gt;mRTplayerMq, RETRY_CMD, -1);
            }
            else{
                printf("io error, mqueue not exist\n");
            }
            break;
        }
        case RTPLAYER_NOTIFY_NOT_SEEKABLE:
        {
            pDemoPlayer-&gt;mSeekable = 0;
            printf("info: media source is unseekable.\n");
            break;
        }
        case RTPLAYER_NOTIFY_DETAIL_INFO:
        {
            int flag = *(int *)(uintptr_t)ext2;
            //printf("detail info: %d\n", flag);
            break;
        }
        default:
        {
            printf("warning: unknown callback from RTplayer.\n");
            break;
        }
    }
}
int cmd_rtplayer_test(int argc, char ** argv)
{
    int inputMode = 0;
    int testMode = 0;
	/*
    printf("argc = %d\n",argc);
    for(int i=0; i &lt; argc;i++){
        printf("argv[%d]=%s\n",i,argv[i]);
    }
	*/
	printf("rtplayer source:%s\n", argv[1]);

    if(argc == 3){
        if( !strncmp("no_shell_input", argv[2], sizeof("no_shell_input")-1) ){
            argc--;
            inputMode = 1;
        }
        else if( !strncmp("test_mode", argv[2], sizeof("test_mode")-1) ){
            argc--;
            testMode = 1;
        }
    }
    if(argc != 2){
        LOGW("the parameter is error,usage is as following:");
        showHelp();
        goto rtp_failed;
    }
#if USE_PREPARE_ASYNC
    int waitErr = 0;
#endif
    DemoPlayerContext* demoPlayer = (DemoPlayerContext*)malloc(sizeof(DemoPlayerContext));
    if(demoPlayer == NULL){
        LOGE("malloc DemoPlayerContext fail");
        goto rtp_failed;
    }
    memset(demoPlayer, 0, sizeof(DemoPlayerContext));
    demoPlayer-&gt;mSeekable = 1;
    demoPlayer-&gt;mRTplayerMq = INVALID_MQD;
    demoPlayer-&gt;inputMode = inputMode;
    demoPlayer-&gt;testMode = testMode;
    demoPlayer-&gt;quitFlag = 0;
    demoPlayer-&gt;mMediaInfo = NULL;
    if(strlen(argv[1])&lt;=0){
        LOGE("url error");
        goto rtp_url_failed;
    }
    demoPlayer-&gt;pUrl = malloc(strlen(argv[1])+1);
    if(!demoPlayer-&gt;pUrl){
        LOGE("pUrl malloc fail");
        goto rtp_url_failed;
    }
    memset(demoPlayer-&gt;pUrl, 0, strlen(argv[1]));
    strcpy(demoPlayer-&gt;pUrl, argv[1]);
#if USE_PREPARE_ASYNC    
     sem_init(&amp;demoPlayer-&gt;mPreparedSem, 0, 0);
#endif
    demoPlayer-&gt;mRTplayer = (RTPlayer*)(uintptr_t)player_init();
    LOGI("demoPlayer.mRTplayer = %p",demoPlayer-&gt;mRTplayer);
    if(!demoPlayer-&gt;mRTplayer){
        LOGE("init rtplayer fail");
        goto rtp_init_failed;
    }

    registerCallback(demoPlayer-&gt;mRTplayer, demoPlayer, callbackFromRTplayer);
    status_t ret = setDataSource_url(demoPlayer-&gt;mRTplayer,demoPlayer,demoPlayer-&gt;pUrl, 0);
    if(ret){
        LOGE("set DataSource url fail");
        goto rtp_prepare_failed;
    }
#if USE_PREPARE_ASYNC
    demoPlayer-&gt;mPreparedFlag = 0;
    if(prepareAsync(demoPlayer-&gt;mRTplayer) != 0)
    {
        printf("TPlayerPrepareAsync() return fail.\n");
    }else{
        printf("preparing...\n");
    }
    struct timespec t;
    t.tv_nsec = 0;
    t.tv_sec = 30;
    waitErr = sem_timedwait(&amp;demoPlayer-&gt;mPreparedSem, &amp;t);
    if(waitErr == -1){
        printf("prepare timeout,has wait %d s\n",t.tv_sec);
        sem_destroy(&amp;demoPlayer-&gt;mPreparedSem);
        goto rtp_prepare_failed;
    }else if(demoPlayer.mError == 1){
        printf("prepare fail\n");
        sem_destroy(&amp;demoPlayer-&gt;mPreparedSem);
        goto rtp_prepare_failed;
    }
    printf("prepared ok\n");
#else
    ret = prepare(demoPlayer-&gt;mRTplayer);
    if(ret){
        LOGE("prepare fail");
        goto rtp_prepare_failed;
    }
#endif
    start(demoPlayer-&gt;mRTplayer);
    demoPlayer-&gt;isPlayingFlag = 1;

    if( mRTplayerMq==INVALID_MQD ){
        mRTplayerMq = mq_open( pcRTplayerMqName, O_CREAT | O_RDWR, DEFAULT_MODE, &amp;xRTplayerMqAttr );
        if(mRTplayerMq==INVALID_MQD){
            LOGE("mq_open fail");
        }
    }
    demoPlayer-&gt;mRTplayerMq = mRTplayerMq;
    rtplayer_clear_cmd(demoPlayer-&gt;mRTplayerMq);

    pthread_attr_t attr;
    pthread_attr_init(&amp;attr);
    struct sched_param sched;
    sched.sched_priority = 4;
    pthread_attr_setschedparam(&amp;attr, &amp;sched);
    pthread_attr_setstacksize(&amp;attr, 32768);
    pthread_attr_setdetachstate(&amp;attr, PTHREAD_CREATE_DETACHED);

    if( pthread_create(&amp;demoPlayer-&gt;mThreadId, &amp;attr, RTplayerThread, demoPlayer) ){
        LOGE("pthread_create failed, quit the rtplayer");
        mRTplayerMq = INVALID_MQD;
        //mq_close(demoPlayer-&gt;mRTplayerMq);
#if USE_PREPARE_ASYNC
        sem_destroy(&amp;demoPlayer-&gt;mPreparedSem);
#endif
        goto rtp_prepare_failed;
    }
    pthread_setname_np(demoPlayer-&gt;mThreadId, "RTplayerThread");

    if(demoPlayer-&gt;inputMode)
        goto rtp_succeed;
    while(1){
        char cRxed = getchar();
        if(cRxed==BACKGROUND_CMD){
            printf("shell input exit, rtplayer will run in the background\n");
            break;
        }
        rtplayer_send_cmd(demoPlayer-&gt;mRTplayerMq, cRxed, 0);
        if(cRxed==QUIT_CMD)
            break;
        usleep(50*1000);
    }
rtp_succeed:
    return 0;
rtp_prepare_failed:
    player_deinit(demoPlayer-&gt;mRTplayer);
rtp_init_failed:
    free(demoPlayer-&gt;pUrl);
rtp_url_failed:
    free(demoPlayer);
rtp_failed:
    return -1;
}
FINSH_FUNCTION_EXPORT_CMD(cmd_rtplayer_test, rtplayer_test, test the rtplayer);

static int cmd_rtplayer_controller(int argc, char ** argv){
    if(mRTplayerMq==INVALID_MQD){
        printf("mRTplayerMq = INVALID_MQD!\n");
        return -1;
    }
    if( (argc!=2) &amp;&amp; (argc!=3) ){
        printf("usage:rtpc &lt;cmd&gt; [data]\n");
        return -1;
    }
    int data = 0;

    if(argc==3)
        data = atoi(argv[2]);
    rtplayer_send_cmd(mRTplayerMq, argv[1][0], data);

    return 0;
}
FINSH_FUNCTION_EXPORT_CMD(cmd_rtplayer_controller, rtpc, control the rtplayer);
</code></pre>
<h2>注意事项</h2>
<ul>
<li>
<p dir="auto">目前 rtplayer/xplayer 仅支持音频解码，且不支持对视频文件进行解封装，因此 rtplayer 播放器应用只支持音频文件的播放。</p>
</li>
<li>
<p dir="auto"><code>void registerCallback(void* handle, void* userData, player_callback_t fn)</code> 函数必须要调用，而且 fn 不能为 NULL。</p>
</li>
<li>
<p dir="auto">回调函数中不能调用 rtplayer 的任何一个接口，如：reset、stop、start 等这些接口不能在回调函数中调用。</p>
</li>
<li>
<p dir="auto">播放本地文件的情况下，set url 时，XPlayer 会进行一次同步 prepare，用于提前获取信息给 parser，因此异步 prepare 前，应对 XPlayerSetDataSourceUrl 的返回值进行判断。</p>
</li>
<li>
<p dir="auto">改变播放器的状态，应满足状态图中的对应的函数调用流程，如播放结束后需要播放下一首歌，应调用 reset 清空信息，进入 idle 状态，再调用 setDataSource_Url 进行填充下一首歌到播放器中</p>
</li>
<li>
<p dir="auto">采取异步 prepare 时（prepareAsync），应注意添加信号量进行同步。</p>
</li>
</ul>
]]></description><link>https://bbs.aw-ol.com/topic/4374/r128-基础组件开发指南-rtos-多媒体解码</link><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 05:29:09 GMT</lastBuildDate><atom:link href="https://bbs.aw-ol.com/topic/4374.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 10 Oct 2023 02:30:05 GMT</pubDate><ttl>60</ttl></channel></rss>