您的位置:首页 > 移动开发 > Android开发

EasyPusher实现Android手机屏幕桌面直播,实时推送操作画面,用于手游直播等应用

2016-09-25 00:34 1021 查看

EasyPusher实现Android手机屏幕桌面直播,实时推送操作画面,用于手游直播等应用

标签:
手机屏幕直播手机桌面直播手游直播EasyPusher手机直播

2016-09-25 00:34
132人阅读 评论(0)
收藏
举报


分类:
手机直播(12)


本文转自EasyDarwin开源团队成员John的博客:http://blog.csdn.net/jyt0551/article/details/52651194

由于Android 5.0提供了捕获当前屏幕画面的SDK,基于该SDK,EasyPusher实现了实时推送手机屏幕画面的功能。经测试,效果很不错,延迟也比较低,画面也比较流畅。该功能可运用到小型会议PPT演示、手游直播等行业。

具体来说,MediaProjection 类可以将当前屏幕画面采集到一个surface里面,而MediaCodec可以从一个surface里面获取视频数据源。我们让MediaProjection投射到MediaCodec创建的Surface,MediaCodec就可以获取到MediaProjection投射的视频了。如图所示:

MediaProjectionMediaProjectionSurfaceSurfaceMediaCodecMediaCodecEasyPusherEasyPusher投射屏幕提供视频源编码编码数据通过Pusher推送

在这里就不再详细描述代码的实现,主要介绍下两个接口:
<code class="hljs applescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">VirtualDisplay createVirtualDisplay (String <span class="hljs-property" style="box-sizing: border-box;">name</span>,
int width,
int height,
int dpi,
int flags,
Surface surface,
VirtualDisplay.Callback callback,
Handler handler)
Creates a VirtualDisplay <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">to</span> capture <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> <span class="hljs-property" style="box-sizing: border-box;">contents</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">of</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> screen.

Parameters
<span class="hljs-property" style="box-sizing: border-box;">name</span>    String: The <span class="hljs-property" style="box-sizing: border-box;">name</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">of</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> virtual display, must be non-empty.
要创建的投射器的名称,非空
width   int: The width <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">of</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> virtual display <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">in</span> pixels. Must be <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">greater than</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0.</span>
投射后视频的宽度,这里的宽度就是实际上后面MediaCodec初始化的宽度.
height  int: The height <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">of</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> virtual display <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">in</span> pixels. Must be <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">greater than</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0.</span>
投射后视频的高度,这里的宽度就是实际上后面MediaCodec初始化的高度.
dpi int: The density <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">of</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> virtual display <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">in</span> dpi. Must be <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">greater than</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0.</span>
投射器的像素密度,未理解啥意思,我们直接用DisplayMetrics的densityDpi即可.
flags   int: A combination <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">of</span> virtual display flags. See DisplayManager <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">for</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> full <span class="hljs-type" style="box-sizing: border-box;">list</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">of</span> flags.
我们传
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR|DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC|DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION 即可。
surface Surface: The surface <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">to</span> which <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> content <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">of</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> virtual display should be rendered, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">or</span> null <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> there <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">is</span> none initially.
投射器要投射到的Surface
callback    VirtualDisplay.Callback: Callback <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">to</span> call when <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> virtual display's state changes, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">or</span> null <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> none.
投射器更改后的状态回调,我们这里不需要,传null即可。
handler Handler: The Handler <span class="hljs-function_start" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">on</span></span> which <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> callback should be invoked, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">or</span> null <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> callback should be invoked <span class="hljs-function_start" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">on</span></span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">the</span> calling thread's main Looper.
回调函数将在该Handler所在的线程调用,我们也不需要,传null即可。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li></ul>
<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">createInputSurface

Surface createInputSurface ()
Requests <span class="hljs-operator" style="box-sizing: border-box;">a</span> Surface <span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">to</span> use <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">as</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> input <span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">to</span> <span class="hljs-operator" style="box-sizing: border-box;">an</span> encoder, <span class="hljs-operator" style="box-sizing: border-box;">in</span> place <span class="hljs-operator" style="box-sizing: border-box;">of</span> input buffers.

该接口创建一个作为编码器输入的Surface。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>


然后,将后者得到的Surface作为第6个参数传给前者,前者就可以获取到屏幕数据了~

如下图所示,在VLC访问RTSP地址,即可看到屏幕直播。



EasyPusher项目见:https://github.com/EasyDarwin/EasyPusher
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐