简介
1.1 MediaPlayer History
Android 1.0→Packet video – Open core
Android 1.6→Open Core 2.0
Android 2.0→Stagefright
Android 2.1→Stagefright
Android 2.3→Stagefright with enhancements
Android 3.0→Stagefright + HLS for first time
Android 4.1 to 4.3→SF – Support for MediaCodec
Android 5.0→MediaSession and MediaController classes introduced
Android中的MediaPlayer播放框架经历了OpenCore,StageFrightPlayer(AwesomePlayer),然后NuPlayerDriver。Android2.3 引入流媒体框架,而流媒体框架的核心是NuPlayer。Android4.0之后HttpLive和RTSP协议开始使用NuPlayer播放器,本地播放还是AwesomePlayer, Android5.0(L版本)之后本地播放也开始使用NuPlayer播放器。
1.2 关于视频播放
播放器进行播放至少有4大部分:source、demux、decoder、output。
1.source:数据源,可能是本地资源文件,也可能是流媒体。如果是流媒体有可能是网路上的各种协议例如:http、rtsp、HLS等。
2.demux 解复用:视频文件一般情况下都是把音视频流通过某种规则放在一起。这种规则就是容器规则。现在有很多不同的容器格式。如ts、mp4、 flv、mkv、avi、rmvb等等。demux的功能就是把音视频流从容器中剥离出来,然后分别送到不同的解码器中。
3.decoder解码:解码器–播放器的核心模块。分为音频和视频解码器。
4.output输出:输出部分分为音频和视频输出。解码后的音频(pcm)和视频(yuv)的原始数据需要得到音视频的output模块的支持才能真正的让人的感官系统(眼和耳)辨识到。
1.3 关于HLS
Android 系统中接触到的流媒体协议主要有三种:Progressive Download,RTSP/ RTCP/RTP,HLS。虽然HLS 协议是竞争对手Apple 的流媒体协议,但是从4.4 开始,android 对HLS 这一块的开发做出了很大改变。
HLS:基于HTTP协议,网络部署中不需要架设专有的流媒体服务器,使用标准的 HTTP WEB 服务器即可,便于大规模部署相
对于常见的流媒体直播协议,例如RTMP协议、RTSP协议、MMS协议等,HLS直播最大的不同在于,直播客户端获取到的,并不是一个完整的数据流。 HLS协议在服务器端将直播数据流存储为连续的、很短时长的媒体文件(MPEG-TS格式),而客户端则不断的下载并播放这些小文件,因为服务器端总是会将最新的直播数据生成新的小文件,这样客户端只要不停的按顺序播放从服务器获取到的文件,就实现了直播,实时性没有RTSP高,有一定的延迟
HLS(HTTP Live Streaming):Apple 的动态码率自适应技术,是苹果公司开发的基于HTTP协议的流媒体解决方案。基本原理是将视频文件或视频流切分成小片(ts)并建立索引文件(m3u8)。首先将一个完整视频分成多个TS视频文件,用户下载m3u8文件,通过m3u8文件的索引地址播放具体的每个小段视频。HLS 基于HTTP 传送音视频,它既支持直播,也支持点播。主要用于PC 和Apple 终端的音视频服务。包括一个m3u(8)的索引文件,TS 媒体分片文件和key 加密串文件。目前Android也已经支持。HLS点播,基本上就是常见的分段HTTP点播,不同在于,它的分段非常小。
m8976平台为例,Android所涉及关键代码目录:
/m8976/frameworks/av/media/libstagefright/httplive/目录下
1.3.1 m3u8文件
服务端:需要服务端配置多码率适配流
比如:
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000
http://example.com/low.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000
http://example.com/mid.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000
http://example.com/hi.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=65000,CODECS="mp4a.40.5"
http://example.com/audio-only.m3u8
1.3.2 TS分片文件
客户端:计算出当前获得的带宽,向服务器请求与当前带宽匹配的m3u8文件,再通过m3u8文件的索引地址播放具体的视频片断ts
For example, Client get M3U8 files, and its Content:
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:140651513
#EXT-X-TARGETDURATION:10
#EXTINF:8,
http://vapp1.fw.live.cntv.cn/cache/289_/seg0/index140651513[140651513].ts
#EXTINF:9,
http://vapp1.fw.live.cntv.cn/cache/289_/seg0/index140651514[140651514].ts
#EXTINF:11,
http://vapp1.fw.live.cntv.cn/cache/289_/seg0/index140651515[140651515].ts
#EXTINF:10,
http://vapp1.fw.live.cntv.cn/cache/289_/seg0/index140651516[140651516].ts
#EXTINF:12,
http://vapp1.fw.live.cntv.cn/cache/289_/seg0/index140651517[140651517].ts
#EXTINF:8,
http://vapp1.fw.live.cntv.cn/cache/289_/seg0/index140651518[140651518].ts
#EXTINF:12,
http://vapp1.fw.live.cntv.cn/cache/289_/seg0/index140651519[140651519].ts
#EXTINF:8,
http://vapp1.fw.live.cntv.cn/cache/289_/seg0/index140651520[140651520].ts
#EXTINF:9,
http://vapp1.fw.live.cntv.cn/cache/289_/seg0/index140651521[140651521].ts
#EXTINF:13,
http://vapp1.fw.live.cntv.cn/cache/289_/seg0/index140651522[140651522].ts
然后根据索引中链接请求下载音视频并进行播放
1.3.3 Android HLS的source 创建
/m8976/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
这里有三种不同的DataSource:HttpLiveSource,RTSPSource,以及GenericSource,HLS对应的是HttpLiveSource。
1.3.4 QCOM解决方案的HLS开关
如何enable HLS function
system.prop
[persist.media.hls.actual_bw]:[1]
[persist.media.hls.asym_bw]:[1]
[persist.media.hls.cust_bw]:[1]
[persist.media.hls.customization]:[1]
[persist.media.hls.image_support]:[1]
[persist.media.hls.start_SeqNo]:[1]
1.3.5 HLS 播放流程
Connect Network->Bandwidth estimate->FetchPlaylist(.m3u8)->FetchFile(.ts)->
decryptBuffer->ParseTs->ExtractorA/V->DecoderA/V->Render
创建入口:
/m8976/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
MediaPlayerService::Client::createPlayer
MediaPlayerFactory::createPlayer
NuPlayerFactory sp createPlayer
return new NuPlayerDriver(pid);
以高通平台为例
/m8976/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
构造函数中mPlayer = AVNuFactory::get()->createNuPlayer(pid);
/m8976/frameworks/av/media/libavextensions/mediaplayerservice/AVNuFactory.cpp
/m8976/vendor/qcom/proprietary/avenhancements/av/mediaplayerservice/ExtendedNuFactory.cpp
ExtendedNuFactory::createNuPlayer(pid_t pid)
创建ExtendedNuPlayer(pid);
/m8976/vendor/qcom/proprietary/avenhancements/av/mediaplayerservice/ExtendedNuPlayer.cpp
ExtendedNuPlayer::setDataSourceAsync
property_get(“persist.media.hls.customization”, value, “0”);
source = new ExtendedHTTPLiveSource(notify, httpService, url, headers);
/m8976/vendor/qcom/proprietary/avenhancements/av/mediaplayerservice/ExtendedHTTPLiveSource.cpp
ExtendedHTTPLiveSource::prepareAsync()
mLiveSession = new ExtendedLiveSession()
mBandwidthEstimator(new BandwidthEstimator())
mLiveSession->connectAsync
/m8976/frameworks/av/media/libstagefright/httplive/LiveSession.cpp
LiveSession::connectAsync 入口
void LiveSession::onConnect
m8976/frameworks/av/media/libstagefright/httplive/PlaylistFetcher.cpp
构造函数中创建mHTTPDownloader
mHTTPDownloader = mSession->getHTTPDownloader();
kWhatFetchPlaylist
mHTTPDownloader->fetchPlaylist
kWhatPlaylistFetched
/m8976/frameworks/av/media/libstagefright/httplive/HTTPDownloader.cpp
HTTPDownloader::fetchPlaylist
fetchFile
/m8976/frameworks/av/media/libstagefright/httplive/LiveSession.cpp
LiveSession::onMasterPlaylistFetched
Bandwidth 检测估算:
/m8976/frameworks/av/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
NuPlayer::HTTPLiveSource::selectTrack
/m8976/frameworks/av/media/libstagefright/httplive/LiveSession.cpp
LiveSession::selectTrack
kWhatChangeConfiguration
LiveSession::changeConfiguration
onChangeConfiguration2
restartPollBuffering();
LiveSession::schedulePollBuffering()
/m8976/vendor/qcom/proprietary/avenhancements/av/stagefright/ExtendedLiveSession.cpp
ExtendedLiveSession::onPollBuffering()
switchBandwidthIfNeeded进行判断
/m8976/frameworks/av/media/libstagefright/httplive/LiveSession.cpp
LiveSession::switchBandwidthIfNeeded
LiveSession::BandwidthEstimator::estimateBandwidth
估算bandwidth
HLS系统结构
内容服务器:mpeg-2 ts流
内容分发
客户端
服务器将摄像头采集的音视频文件打包成符合MPEG-2 系统层标准的传输流(TS)格式进行输出
然后被流分割软件分割成连续的后缀是.ts 的小文件序列,同时还会生成一个.m3u8 索引文件,通过HTTP 协议分发给客户端。
客户端软件可以根据实时网络传输速率和缓冲区占有率的变化,在这些不同的TS 流之间自动切换。
客户端根据URL,得到索引文件(m3u8),然后根据实时的网络传输速率,在索引文件中选取对应的索引,然后从网络服务器上下载媒体文件,每一个媒体文件(即分割的TS 文件)都是整个流的一部分
通常播放器会先下载几个媒体文件缓存下来,积攒到一定数量后,进行播放。当媒体文件加密时,客户端还负责获取解密文件
HLS 自适应测试
测试平台的搭建参照: HLS 测试平台搭建
3.1 测试网站
http://hls.ftgroup-devices.com
Test Set:
4.adaptation to bandwidthTest:
4.03 - Significant changes of bandwidth
Run: Run_7-12_14-46-18
Test Parameters:
Step: Test server - Bandwidtch decreaseDescription:
1. Activate the network trace
2. Go to http://hls.ftgroup-devices.com
3. Select 1-19.0
4. Play the stream for 5min
5. Limit the bandwidth to 500kbps