HLS+FMP4方案对H.265+AAC支持要点

​问题背景:

2017年的苹果WWDC大会上,苹果宣布HEVC支持HLS,涉及了iOS、MacOS和tvOS等系统终端。苹果之所以乐意这个事情,首先HLS就是他们家的,近些年一直把HLS致力于推成Web标准,其次苹果手握大量H.265的专利,也不想谷歌的AOM对应的VP9标准一家独大,HLS虽然延时有些大,但不可否认的,目前HLS是跨平台做的最好的协议。

 

我们之所以想实现下这块是因为近年来:

1.视频监控领域现在摄像头和NVR对H.265支持的越来越好,很多设备后台默认配置现在就是H.265,所以设备端(IPC和NVR)支持了,播放端也要跟着支持起来;

2.有实实在在的Web端播放需求,随着目前设备上云速度加快,无论是传统行业还是消费类摄像头,现在不仅仅在Native App播放,也有很多Web端播放需求。像在Web端分享一条链接就能在小程序上直播视频就很有用,特别是和一些报警联动起来,的确会方便不少;

3.视频监控还有一个重要需求就是视频回放功能,因为事后查询很必要,H.265相比较H.264在1080P分辨率下,要节省将近50%的带宽。同时在画质不变情况下,相比较H.264码率也可以将近降低50%左右,所以无论从存储和带宽压力和还是从画质提升上,HEVC编码都是非常刚需的。 

综上,HLS在分发视频时不仅仅要支持H.264,也要支持HEVC,可以根据请求客户端类型和设备码流编码格式进行匹配分发。

 

智媒黑板报

了解更多关于音视频&IOT,欢迎关注公众号:智媒黑板报

 


注:

1. HEVC即High Efficency Video Coding是AVC(Advance Video Codeing)的演进版本,其中HEVC又称为H.265,而AVC也叫做H.264,这两个其实是一回事。至于为啥有两个别名,简单来说视频编码标准以前主要由两个国际化标准组织制定,其中H.26X系列,是由国际电信联盟电信标准化部门ITU-T制定,AVC和HEVC主要是ISO国际标准化组织MPEG制定,从H.264开始,它两联合制定过视频编码标准,所以具有了两个名字,但是实际是一回事。对于下一代标准也在去年正式定稿,其中ITU-T称为H.266,MPEG则称为VCC,感兴趣的可以了解下视频编码的发展历程。

 


支持原理:

HLS支持H.264已经比较成熟,就是将码流进行MPEG-TS切片,然后通过HLS协议分发出去,客户端通过解析m3u8里面的TS片段对应的URL,然后不断循环拉TS片段进行播放即可。目前在Web端,移动端支持的都非常好,系统无论是IOS还是Android 基本都可以原生支持播放。

HLS支持HEVC,采用的技术和H.264基本一样,其中变化点主要是H.265的切片文件封装格式是Fragmented Mp4简称FMP4,其次m3u8里面的版本采用V7,服务端只要做好适配即可。

给三个链接,大家可以抓包学习协议细节:

HEVC HLS with fMP4:

http://bitmovin-a.akamaihd.net/content/dataset/multi-codec/hevc/stream_fmp4.m3u8

HEVC HLS with TS (not supported by Apple):

http://bitmovin-a.akamaihd.net/content/dataset/multi-codec/hevc/stream_ts.m3u8

HEVC MPEG-DASH:

http://bitmovin-a.akamaihd.net/content/dataset/multi-codec/hevc/stream.mpd

 

其中FMP4封装格式是HTML5的Media Source Extensions支持的封装格式,像B站的flv.js项目核心就是将FLV文件流转封装为FMP4片段,然后通过该接口送给浏览器进行解码播放,同时FMP4也是DASH协议的媒体文件封装格式,它和MP4封装格式非常类似,其实就是把大的MP4文件进行切片,每个切片都有它自己的meta数据,这样就可以单独播放并且特别适合网络渐进式传输和渐进式播放,同时也方便支持Trick-Play播放。大体结构示意图如下:

HLS+FMP4方案对H.265+AAC支持要点_第1张图片

用MP4 Reader解析了一个FMP4文件:

HLS+FMP4方案对H.265+AAC支持要点_第2张图片

 

 


支持要点:

1. 服务端支持HEVC和H.264相比有啥不同?

主要在拉到设备端原始码流后,对NALU TYPE的判断有不同。 

其中收到H.264判断方法如下:

int nalu_type = buf[0] & 0x1F;

其中nalu_type为5则表示IDR帧,6表示SEI、7表示SPS、8表示PPS;

对HEVC的NALU类型判断:

int nalu_type = (buf[0] & 0x7E)>>1;

//or

int nalu_type = (buf[0] >> 1) & 0x3F;

其中nalu_type19代表IDR帧,32位VPS、33位SPS、34为PPS、39为SEI;

网上这块内容非常多,可以找来学习看下,不再赘述。

 


2. 基于Ffmpeg对MPEG-TS和FMP4的切片需要注意哪些?

封装这块直接基于Ffmpeg进行即可,简单快捷,没有必要自己完整实现这个。其中适配两种封装格式比较简单,不清楚FFMPEG接口的可以参考下面链接进行学习,遇到需要兼容的问题是:

音频部分:兼容MPEG-TS的ADTS和FMP4的ASC音视频规格参数

音频我们采用的AAC格式,对于FLV、MP4、FMP4和Mov封装格式,封装音频AAC时需要去掉ADTS头形成MPEG-4 Audio Specific Configuration bitstream,对于MPEG-TS封装格式则需要加上ADTS头,这是在音频方面需要兼容的。

由于我们采用了FFmpeg进行打包和封装MPEG-TS和FMP4片段,则借助FFMPEG的Bitstream Filters即BSF机制即可。

音频我们去掉ADTS头形成ASC,一般就是将读出来的AvPacket进行过滤器进行转化下即可:

 

示例代码:

AVBitStreamFilterContext*m_pAacbsf = = av_bitstream_filter_init("aac_adtstoasc");

HLS+FMP4方案对H.265+AAC支持要点_第3张图片

视频部分:

无论是H.264还是H.265,封装格式都有两种:AnnexB( Annex B of the ITU-T H.264 specification)和AVCC/HVCC格式,其中前者就是在每帧如SPS PPS IDR前面加上StartCode即00 00 00 01 或者00 00 01作为视频帧之间的分界符,后者则没有StartCode,是将SPS、PPS和IDR帧封装成Container(比如FLV的TAG,MP4的Box),再在前面加上该视频帧的长度即可,一般长度用四字节表示。

视频部分一般我们能拿到裸流,所以分别按照不同封装格式的要求进行封装即可。如果是MPEG-TS到FMP4的转化则可以继续使用FFMPEG的BSF机制进行码流过滤:

HLS+FMP4方案对H.265+AAC支持要点_第4张图片


注:

FFMPEG的 Bitstream Filters作用:

1.比特流滤波器对编码后的数据进行操作(压缩码流)。

2.不进行解码操作,但是支持比特流级别的修改。


3. M3U8要进行升级变化?

这块我们只做了最简单的适配和兼容,其中变化很小,其它字段如果你要用可以参考HLS协议规范自行添加。

HLS+FMP4 H.265切片的对应m3u8直播文件

有些媒体格式需要一个 format-specific sequence 来初始化一个 parser, 在 Media Segment 被 parse 之前. 这个字段叫做 Media Initialization Section, 通过 EXT-X-MAP tag 来指定,对于FMP4的初始化Init.mp4的下载链接则在这里指定。

 

HLS+FMP4方案对H.265+AAC支持要点_第5张图片

HLS+TS H.264切片的对应m3u8回放文件

HLS+FMP4方案对H.265+AAC支持要点_第6张图片

HLS+FMP4 H.265切片的对应m3u8回放文件 

HLS+FMP4方案对H.265+AAC支持要点_第7张图片

 


4. 当前客户端支持情况怎么样?

在苹果产品家族,支持HLS+Fmp4方案,至少应该在 iOS 11, tvOS 11 及 macOS 10.13以后系统进行测试,安卓我们也进行了测试,其中在安卓8以上手机部分机型支持。总体而言,用系统自带浏览器和微信上测试,IOS基本没有啥问题,播放很顺畅,对协议和媒体的兼容性也较好,但是安卓支持的不是很好,例如一些时间戳稍微有问题就不能播放或者黑屏。

 


5. H.264是否可以采用HLS+FMP4方案?

就切片和封装格式而言,FMP4可以封装H.265当然也可以封装H.264,但是兼容性的问题主要是有些原生浏览器客户端不能支持HLS+FMP4方案(包括解析HLS协议和解封装FMP4),所以对于H.264我们依然采用老方案即HLS+MPEG-TS,对于H.265我们才采用HLS+FMP4.

 


6. 对于音视频编码要求和一些HLS的M3U8,还有什么具体要求?

可能有些音视频在播放过程中存在一定的问题,这时需要进一步参考HLS规范,看对一些细节方面的要求,可以参考下面链接。

https://developer.apple.com/documentation/http_live_streaming/hls_authoring_specification_for_apple_devices#//apple_ref/doc/uid/TP40016596-CH4-SW1

比较重要的几条:

HEVC的Profile,Level和Tier必须小于或等于Main10的Profile,Level 5.0,High Tier;

HEVC 的帧率必须控制在60fps以内,实际我们一般就是30fps或者25fps;

HEVC的分辨率,我们设备端设置的为720P或者1080P;

 


测试情况:

下面是一些我们的测试截图:左图iPhone8手机IOS13.3微信端测试,右图Vivo安卓8.1自带浏览器测试,同时我们在IOS12小程序和安卓10上测试也是可以的。

HLS+FMP4方案对H.265+AAC支持要点_第8张图片  


最后总结:

这篇文章主要讲了HLS协议如果要支持对HEVC进行FMP4切片,大概会遇到哪些问题,已经这些问题的基本思路,同时给出了最简单的实现效果。在调试过程中还要解决音视频时间戳问题导致的黑屏、花屏和音画不同步等问题。这些问题不属于HLS的范畴,所以没进行进一步详细描述,同时也有些HLS的新字段没启用,这点要根据场景和需求来开发。

 


参考链接:

1.https://developer.apple.com/streaming/

2. https://www.jianshu.com/p/1bfe4470349b

3. https://tools.ietf.org/html/rfc8216

4.https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#page-7

5. https://developer.apple.com/videos/play/wwdc2016/504/

6. https://blog.csdn.net/leixiaohua1020/article/details/39802913

7.http://www.ffmpeg.org/ffmpeg-bitstream-filters.html

 

 


往期文章回顾:

译:构建音视频直播应用需要考虑的12件事

流媒体传输协议:RTMP、HLS和RTSP介绍

基于HLS-TS&RTMP-FLV的微信小程序点直播方案

一图看懂音视频核心技术栈(框架、工具和场景))

国产开源流媒体SRS4.0对视频监控GB28181的支持

从方块效应&呼吸效应看编码量化参数对流控的作用

家庭消费类摄像头选择攻略和隐私保护小建议

音视频封装小总结(PS TS 和FLV)

SDP在RTSP、国标GB28181、WebRTC中的实践

视频监控摄像头的互联网化实践思路

在HTML5上开发音视频应用的五种思路

周末活动回顾:视频质量主观评价、实时RTC和AV1

音视频封装:MP4结构概述和分析工具

音视频解封装:MP4核心Box详解及H264&AAC打包方案

音视频基础知识-时间戳的理解

音视频封装格式:AAC音频基础和ADTS打包方案详解

从人类的第一次直播聊聊视频监控行业

音视频压缩:H264码流层次结构和NALU详解

音视频传输:RTP协议详解和H.264打包方案

音视频常见问题分析和解决:延时和抖动


个人转载内容至朋友圈和群聊天,无需特别申请版权许可。

引用转载该订阅号文章,注明文章来源即可。

记得右下角点“在看”,还可以关注该订阅号,防止遗漏推送哦

 


今天就说这么多,祝您工作顺利!

 

 

你可能感兴趣的:(音视频开发)