关于DASH直播实现的笔记
1. dash是什么
关于介绍百度一下就好了,以下是相关介绍
https://it3q.com/article/78
2. 关于dash的开源代码
https://github.com/ireader/media-server
我参照的相关例子是media-server\libdash\test\dash-dynamic-test.cpp,这是用一个flv文件作为输入进行的dash实现
flv解析可以参照:https://www.cnblogs.com/musicfans/archive/2012/11/07/2819291.html
编译好之后,可以直接跑一下开源的例子,例子显示会一卡一卡的,是因为http请求数据速度 < 生成视频片段的速度,导致会丢一些数据,同步做的不好。
3. 海思上实现dash直播
1)fmp4的生成
首先海思上venc出来的数据不同于flv封装好的数据,需要知道其中的差异,然后再将venc编码好的数据封装成dash所需要的格式
venc出来的数据叫annex-b,本人配置的是h265的编码
转换其实media-server那边也有相关的例子,media-server\libmov\test\mov_writer_h265.c
实际上annex-b转fmp4只需用到了media-server\libflv\source下的mpeg4-annexbtomp4.c和hevc-annexbtomp4.c上面的接口
关于HVCC的生成这边也有相关的例子:
hevc-annexbtomp4.c --》void hevc_annexbtomp4_test(void)
到这里应该可以实时将venc编码出来的h265数据装换成fmp4
2)数据的传输
数据传输采用的是http,流程如下:
- 下载MPD文件,解析DASH相关信息;
- 下载视频的Initialization Segment和音频的Initialization Segment;
- 下载视频的第一个分片,下载音频的第一个分片;
- 当视频和音频的第一个分片都下载完,播放器内部再进行一些相关处理后,就可以开始播放出画面。后续就是不断轮询更新MPD文件和下载后续的音频和视频分片。
4.关于mpd文件的解释
<?xml version="1.0" encoding="UTF-8"?> <MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:dash:schema:mpd:2011" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd" type="dynamic" minimumUpdatePeriod="PT1S" <!--MPD最低限度更新时间--> timeShiftBufferDepth="PT6S" <!--MPD最低限度更新时间*缓存个数+1> availabilityStartTime="2022-11-25T06:13:06Z" minBufferTime="PT1S" <!--最小的segment时长--> publishTime="2022-11-25T06:13:21Z" profiles="urn:mpeg:dash:profile:isoff-live:2011"> <Period start="PT0S" id="dash"> <!--周期--> <AdaptationSet contentType="video" segmentAlignment="true" bitstreamSwitching="true"> <!--自适应子集--> <Representation id="H264" mimeType="video/mp4" codecs="avc1.4d402a" width="640" height="480" frameRate="25" startWithSAP="1" bandwidth="53254256"> <!--码流--> <SegmentTemplate timescale="1000" media="live-$Time$.m4v" initialization="live-init.m4v"> <!--片段--> <!--timescale:时间的粒度,1000表示1000个单位为1s--> <!--duration:时间粒度的个数--> <SegmentTimeline> <S t="10000" d="980"/> <S t="11000" d="980"/> <S t="12000" d="980"/> <S t="13000" d="980"/> <S t="14000" d="980"/> </SegmentTimeline> </SegmentTemplate> </Representation> </AdaptationSet> <AdaptationSet contentType="audio" segmentAlignment="true" bitstreamSwitching="true"> <Representation id="AAC" mimeType="audio/mp4" codecs="mp4a.40.2" audioSamplingRate="48000" startWithSAP="1" bandwidth="324432"> <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/> <SegmentTemplate timescale="1000" media="live-$Time$.m4a" initialization="live-init.m4a"> <SegmentTimeline> <S t="9001" d="982"/> <S t="10004" d="981"/> <S t="11007" d="981"/> <S t="12009" d="982"/> <S t="13012" d="981"/> </SegmentTimeline> </SegmentTemplate> </Representation> </AdaptationSet> </Period> </MPD>
详细可以参照:https://zhuanlan.zhihu.com/p/429687481
5. 关于我遇到的问题
1)花屏
因为linux和liteos对于venc编码出来的数据处理不同,具体看海思提供的demo
2)编码速度快于播放器请求数据的速度,因为我用了队列在存储转换得到的fmp4,播放太慢就会导致队列满了,丢弃掉一些数据,画面看起来一卡一卡的
大概率是pts/dts不对,我看media-server上的例子pts基本是1s,因为不太清楚里面的实现,我把帧率改成30,一个GOP刚好就1s,一个GOP存储成一个fmp4片段,结果就好了很多