关于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,流程如下:

  1. 下载MPD文件,解析DASH相关信息;
  2. 下载视频的Initialization Segment和音频的Initialization Segment;
  3. 下载视频的第一个分片,下载音频的第一个分片;
  4. 当视频和音频的第一个分片都下载完,播放器内部再进行一些相关处理后,就可以开始播放出画面。后续就是不断轮询更新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片段,结果就好了很多

posted @ 2022-12-29 16:01  Hecarim丶  阅读(181)  评论(0编辑  收藏  举报