文档章节

使用MediaCodec和RTMP做直播推流

 量子
发布于 2017/06/11 11:36
字数 1414
阅读 2640
收藏 196
点赞 5
评论 25

本项目完全开源 项目Github地址:AndroidInstantVideo 码云地址:AndroidInstantVideo

目前开源的项目或市面上的Android直播客户端主要是用ffmpeg来实现推流的。本文将介绍使用Android原生的视频编码类MediaCodec实现直播推流。

数据流及大致原理

这里所说的直播,就是将你的客户端产生的视频数据,实时发送到服务器上。服务器上的数据再实时地发送到播放客户端上。

  • 以视频数据为例:

获取Camera画面 首先是摄像头拍摄得到原始画面数据,这里原始画面数据的格式我们不用管,因为我们使用的是MediaCodec,所以我们会使用 camera.setPreviewTexture(surfaceTexture) 来利用Camera获取到的画面。

此处的原理可忽略,大致说明的话,就是Camera会把获得的画面保存为OpenGL的一个纹理,我们使用这个纹理就能使用Camera的画面。

绘制画面 在获得画面之后,我们要把这个画面(纹理)“画”到MediaCodec上。

如何画? MediaCodec提供一张’白纸’,也就是一个Surface,供我们把纹理画到上面。此处的API是 MediaCodec.createInputSurface()

怎么画?用Canvas画。当然不是一般的Canvas,我用了这个开源项目android-openGL-canvas

H264数据 画上去后,MediaCodec就会帮我们把原始画面数据,压缩成相应的视频数据,目前我这里是压缩成H264数据。 所谓的H264数据,其实只是一堆堆的byte[]数组。在项目的例子,我把H264数据写成了文件,可以用某些播放器播放(例如PotPlayer)。

RTMP 我使用了一个开源项目,可以将视频数据封成RTMP包,发送到服务器上。 LibRtmp-Client-for-Android

总结 数据流可以这样看 Camera -> SurfaceTexture -> Surface -> MediaCodec -> encode data(byte[]) -> RTMPMuxer -> Server

  • 音频数据:

相对简单一些,就是从AudioRecord里获取原始音频数据(byte[]),编码成AAC数据(也是byte[]),然后给RTMPMuxer,封装成RTMP包,发到服务器

麦克风MIC -> AudioRecord -> voice data(就是byte[]) -> MediaCodec -> encode data(就是byte[]) -> RTMPMuxer -> Server

  • Muxer

前面有提到有视频的RTMP包和音频的RTMP包,分别是将单元H264和单元AAC封装成RTMP包,发到服务器。这些包之间有什么规律? 这些包之间是按时间顺序排列的,MediaCodec返回编码数据时,会返回编码数据的时间戳。但注意编码成RTMP包时,取的是相对时间戳,也就是说取到时间戳时,需要计算与上一个包的时间戳的差值,写到RTMP包里。

另外RTMP流本质上是FLV格式的音视频,这里也提供了写成FLV文件的功能。

效果图

PC播放端  PC播放端

Android推流端 Android推流端

视频帧图像处理

前面提到视频帧的图像处理,实际上也是利用了android-openGL-canvas

关键代码如下:

    ...
    streamPublisher.prepareEncoder(streamPublisherParam, new H264Encoder.OnDrawListener() {
        @Override
        public void onGLDraw(ICanvasGL canvasGL, SurfaceTexture surfaceTexture, RawTexture rawTexture, @Nullable SurfaceTexture outsideSurfaceTexture, @Nullable BasicTexture outsideTexture) {
            drawVideoFrame(canvasGL, outsideSurfaceTexture, outsideTexture);

            Loggers.i("DEBUG", "gl draw");
        }
    });
    ...

    private void drawVideoFrame(ICanvasGL canvasGL, @Nullable SurfaceTexture outsideSurfaceTexture, @Nullable BasicTexture outsideTexture) {
        // Here you can do video process
        // 此处可以视频处理,例如加水印等等
        TextureFilter textureFilterLT = new BasicTextureFilter();
        TextureFilter textureFilterRT = new HueFilter(180);
        int width = outsideTexture.getWidth();
        int height = outsideTexture.getHeight();
        canvasGL.drawSurfaceTexture(outsideTexture, outsideSurfaceTexture, 0, 0, width /2, height /2, textureFilterLT);
        canvasGL.drawSurfaceTexture(outsideTexture, outsideSurfaceTexture, 0, height/2, width/2, height, textureFilterRT);

    }
    ...

如上所示,可以使用各种Filter实现对视频帧图像的处理。总而言之,可以像Canvas那样在视频帧上绘制各种东西。当然要在图上画文字就只能用bitmap代替了。

码率bit/s

在使用MediaCodec时,需要设置码率。这个码率是根据视频分辨率,色彩格式算出来的。

    public H264Encoder(int width, int height, int bitRate, int frameRate, int iframeInterval, final EglContextWrapper eglCtx) throws IOException

其中bitRate就是码率,单位bit/s

一些计算方法可以参考此文: What bitrate should I use when encoding my video? Output size Bitrate Filesize 320x240 pixels 400 kbps 3MB / minute 480x270 pixels 700 kbps 5MB / minute 1024 x 576 pixels 1500 kbps 11MB / minute 1280x720 pixels 2500 kbps 19MB / minute 1920x1080 pixels 4000 kbps 30MB / minute

此方法大部分情况下够用,但是对于复杂视频处理还欠缺。 例如 对比下图的无处理效果(一张纹理) one_effect.png

对于下图这样处理效果(2个画面用的是与上图同样大小的纹理,虽然我设置显示的尺寸不一样),码率是上图的2倍左右。 process_material.png

测试服务器

需要测试的话,请自行搭建RTMP服务器。我用的是自己搭建的Nginx服务器,用的Module是nginx-rtmp-module。搭建服务器不需要写代码,根据教程敲几行命令就行。 可以用开源直播软件OBS对比播放效果。 播放器用各种都行,VLC,PotPlayer,ffplay都可以。 我用的是ffplay,注意,因为只是简单的服务器,所以要先开播放器连接后再开始启动推流。 我使用的命令是 .\ffplay.exe "rtmp://localhost:19305/live/room live=1"

另外可以使用一下软件查看生成的文件的详情。

看H264文件 H.264视频码流解析--雷霄骅

h264.png

看aac文件 AAC音频码流解析--雷霄骅

aac.png

看flv文件 FLV封装格式解析--雷霄骅

flv.png

感谢雷神。

声明

本项目完全开源,项目Github地址:AndroidInstantVideo 本项目为个人开源项目,目前只做过简单的测试,如果要使用的话,请自行多测试,有问题可以到我的Github项目地址提出。

最后

您的打赏是对作者的最大支持!!当然在Github上点个Star也是很大的支持哈哈。 支付宝.jpg 微信.png

© 著作权归作者所有

共有 人打赏支持
粉丝 7
博文 1
码字总数 1414
作品 0
广州
加载中

评论(25)

量子

引用来自“zhudegao”的评论

楼主 ,你好 。能否把Camera 画面 和绘制画面的关键代码发一发 谢谢

引用来自“量子”的评论

文中提到github地址里有。在github的都可下载
https://github.com/ChillingVan/android-openGL-canvas

https://github.com/ChillingVan/AndroidInstantVideo

引用来自“zhudegao”的评论

恩,我好好研究下,要本地保存MP4 大神 有啥办法的:laughing:
使用MediaMuxer
z
zhudegao

引用来自“zhudegao”的评论

楼主 ,你好 。能否把Camera 画面 和绘制画面的关键代码发一发 谢谢

引用来自“量子”的评论

文中提到github地址里有。在github的都可下载
https://github.com/ChillingVan/android-openGL-canvas

https://github.com/ChillingVan/AndroidInstantVideo
恩,我好好研究下,要本地保存MP4 大神 有啥办法的:laughing:
量子

引用来自“zhudegao”的评论

楼主 ,你好 。能否把Camera 画面 和绘制画面的关键代码发一发 谢谢
文中提到github地址里有。在github的都可下载
https://github.com/ChillingVan/android-openGL-canvas

https://github.com/ChillingVan/AndroidInstantVideo
z
zhudegao
楼主 ,你好 。能否把Camera 画面 和绘制画面的关键代码发一发 谢谢
灵魂架构师
灵魂架构师
android-key
android-key
不错
量子

引用来自“sknown”的评论

H264视频专用分析这个软件哪里下,没找到
之前放错链接了,不好意思。
http://blog.csdn.net/leixiaohua1020/article/details/17933821
s
sknown
H264视频专用分析这个软件哪里下,没找到
萍水相逢OSC
萍水相逢OSC

引用来自“夏渚汐风”的评论

引用来自“量子”的评论

引用来自“夏渚汐风”的评论

大哥,你没发现颜色都变了吗
如果指的是文章里的图的话,本身是为了展示图像处理的效果变色的(用了HueFilter)

回复@量子 : 还以为是bug呢

@夏渚汐风
你我的宿命
你我的宿命
沙发
安卓直播推流客户端--Yasea

Yasea是一个100%纯Java写的,完全开源的安卓直播推流客户端。它使用MediaCodec系统接口对H.264和AAC进行硬编码,封装FLV格式,推送至RTMP服务器。延迟达到毫秒级别。 演示: 下载APK安装后,...

我的上铺叫路遥 ⋅ 2016/06/01 ⋅ 2

Yasea v1.0 发布,安卓直播推流客户端

Yasea v1.0 release 发布了,Yasea是一个100%纯Java写的,完全开源的安卓直播推流客户端。它使用MediaCodec系统接口对H.264和AAC进行硬编码,封装FLV格式,推送至RTMP服务器。延迟达到毫秒级...

我的上铺叫路遥 ⋅ 2016/06/05 ⋅ 4

Yasea 1.0 preview 发布,安卓直播推流客户端

Yasea 1.0 preview 发布了,Yasea是一个100%纯Java写的,完全开源的安卓直播推流客户端。它使用MediaCodec系统接口对H.264和AAC进行硬编码,封装FLV格式,推送至RTMP服务器。延迟达到毫秒级别...

我的上铺叫路遥 ⋅ 2016/06/01 ⋅ 0

Yasea v1.1 发布,安卓直播推流客户端

Yasea v1.1 发布了!完全开源的安卓直播推流客户端。它使用MediaCodec系统接口对H.264和AAC进行硬编码,封装FLV格式,推送至RTMP服务器。延迟达到毫秒级别。 由于引进libyuv,Yasea从此告别了...

我的上铺叫路遥 ⋅ 2016/07/13 ⋅ 11

我有一台带摄像头的PC和阿里云,怎么进行一场直播?

准备工作 开通阿里云直播服务:阿里云直播服务接收直播流,并提供直播播放地址,完成一场直播需要先开通阿里云直播服务,在 视频直播产品主页 中单击 立即开通,开通阿里云直播服务。 添加直...

樰篱 ⋅ 04/24 ⋅ 0

直播,音视频编码器和解码器(EasyDarwin)-Android

使用摄像头采集视频数据,并通过MediaCodec进行H264编码,之后打包成RTSP格式并上传的。 TextuewView也提供了一个setTransform方法,该方法接收一个matrix参数,使用该参数对当前的渲染内容进...

shareus ⋅ 05/18 ⋅ 0

如何快速搭建一个完整的移动直播系统?

移动直播行业的火热会在很长一段时间内持续,通过和各行业的整合,从而成为具有无限可能性的行业。主要因为以下三个原因: 移动直播的UGC生产模式比PC端的直播更明显,人人都有设备,随时随地...

我是王雪梨 ⋅ 2016/07/18 ⋅ 3

Android 音视频开发入门指南(2)

GLSurfaceView是OpenGL中的一个类,也是可以预览Camera的,而且在预览Camera上有其独到之处。独到之处在哪?当使用Surfaceview无能为力、痛不欲生时就只有使用GLSurfaceView了,它能够真正做...

shareus ⋅ 04/23 ⋅ 0

关于公网摄像机直播公网视频直播的基本思考方法

前言 目前可以说EasyDarwin接收到的用户需求应该是国内最前沿的,当前视频风口是什么,我们收到的需求就会很多,作为第一手需求接入的我们,很明显感觉到对原理的熟悉、对流程的把握以及对需...

xiejiashu ⋅ 2017/12/27 ⋅ 0

Mac中配置nginx的rtmp协议

背景 想要在mac上面,通过ffmpeg、nginx搭建本地流媒体服务,也就是发布rtmp协议。对ffmpeg、nginx和rtmp都不太熟悉,这里仅仅是一个对流媒体服务器的模仿,最终能够初步共享自己的电脑桌面,...

亚林瓜子 ⋅ 2017/11/29 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Linux中的端口大全

1 被LANA定义的端口 端口 名称 描述 1 tcpmux TCP 端口服务多路复用 5 rje 远程作业入口 7 echo Echo 服务 9 discard 用于连接测试的空服务 11 systat 用于列举连接了的端口的系统状态 13 d...

寰宇01 ⋅ 9分钟前 ⋅ 0

Confluence 6 如何备份存储文件和页面信息

备份的 ZIP 文件包含有 entities.xml,这个 XML 文件包含有 Confluence 的所有页面内容和存储附件的目录。 备份 Zip 文件结构 页面的附件是存储在附件存储目录中的,通过页面和附件 ID 进行识...

honeymose ⋅ 12分钟前 ⋅ 0

【每天一个JQuery特效】根据状态确定是否滑入或滑出被选元素

主要效果: 本文主要采用slideToggle()方法实现以一行代码同时实现以展开或收缩的方式显示或隐藏被选元素。 主要代码如下: <!DOCTYPE html><html><head><meta charset="UTF-8">...

Rhymo-Wu ⋅ 16分钟前 ⋅ 0

度量.net framework 迁移到.net core的工作量

把现有的.net framework程序迁移到.net core上,是一个非常复杂的工作,特别是一些API在两个平台上还不能同时支持。两个类库的差异性,通过人工很难识别全。好在微软的工程师们考虑到了我们顾...

李朝强 ⋅ 21分钟前 ⋅ 0

请不要在“微服务”的狂热中迷失自我!

微服务在过去几年一直是一个非常热门的话题(附录1)。何为“微服务的疯狂”,举个例子: 众所周知,Netflix在DevOps上的表现非常棒。Netfix可以做微服务。因此:如果我做微服务,我也将非常...

harries ⋅ 22分钟前 ⋅ 0

oAuth2 升级Spring Cloud Finchley.RELEASE踩坑分享

背景 6.19号,spring团队发布了期待已久的 Spring Cloud Finchley.RELEASE 版本。 重要变化: 基于Spring Boot 2.0.X 不兼容 Spring Boot 1.5.X 期间踩过几个坑,分享出来给大伙,主要是关于...

冷冷gg ⋅ 52分钟前 ⋅ 0

OSChina 周一乱弹 —— 理发师小姐姐的魔法

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @冰冰棒- :分享田馥甄的单曲《My Love》 《My Love》- 田馥甄 手机党少年们想听歌,请使劲儿戳(这里) @Li-Wang :哎,头发又长了。。。又要...

小小编辑 ⋅ 今天 ⋅ 8

Kafka1.0.X_消费者API详解2

偏移量由消费者管理 kafka Consumer Api还提供了自己存储offset的功能,将offset和data做到原子性,可以让消费具有Exactly Once 的语义,比kafka默认的At-least Once更强大 消费者从指定分区...

特拉仔 ⋅ 今天 ⋅ 0

NEO智能合约之发布和升级(二)

接NEO智能合约之发布和升级(一),我们接下来说说智能合约的升级功能。 一 准备工作 合约的升级需要在合约内预先设置好升级接口,以方便在升级时调用。接下来我们对NEO智能合约之发布和升级...

红烧飞鱼 ⋅ 今天 ⋅ 0

个人博客的运营模式能否学习TMALL天猫质量为上?

心情随笔|个人博客的运营模式能否学习TMALL天猫质量为上? 中国的互联网已经发展了很多年了,记得在十年前,个人博客十分流行,大量的人都在写博客,而且质量还不错,很多高质量的文章都是在...

原创小博客 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部