MPEG-DASH开发

DASH(Dynamic Adaptive Streaming over HTTP),在GStreamer中,DASH,HLS,MSS的adaptive_demux_sink_event收到GST_EVENT_EOS之后,才会调用  demux_class->process_manifest (demux, manifest_buffer))处理播放列表。播放列表组织如下:

MPD文件由一个或多个Period构成,简单来讲,period就是周期,就是时间轴上的一段时间,如下图所示:

mimeType是互联网媒体类型(Internet media type)的一种别称。标准的MIME结构是“类型名/子类型名”,目前已被注册的类型名有application、audio、example、image、message、model、multipart、text,以及video,如audio/mp4表示MP4音频文件,video/mp4表示MP4视频文件。
        AdaptationSet包含一个或者多个音视频媒体的MIME TYPE类型描述,通常包含若干个representations,一个period由一个或者多个AdaptationSet构成。DASH对段定义了三种表示方式,Representation由如下这几个选项之中的一个组成:
        (1) 段列表表示:由SegmentList元素列表组成;

<?xml version="1.0"?>
<!-- MPD file Generated with GPAC version 0.5.2-DEV-rev322-gf6fed6c-master  at 2015-05-11T10:14:04.782Z-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500S" type="static" mediaPresentationDuration="PT0H22M36.255S" maxSegmentDuration="PT0H0M10.077S" profiles="urn:mpeg:dash:profile:mp2t-main:2011"><ProgramInformation moreInformationURL="segment/"><Title>547_dash.mpd generated by GPAC</Title></ProgramInformation><BaseURL>segment/</BaseURL><Period duration="PT0H22M36.255S"><AdaptationSet segmentAlignment="true" maxWidth="1920" maxHeight="1080" par="16:9"><ContentComponent id="256" contentType="video" /><ContentComponent id="257" contentType="audio" /><Representation id="1" mimeType="video/mp2t" width="1920" height="1080" audioSamplingRate="44100" startWithSAP="1" bandwidth="6672839"><SegmentList timescale="90000" duration="900000" presentationTimeOffset="3003"><RepresentationIndex sourceURL="segment.six"/><SegmentURL media="segment1.ts"/><SegmentURL media="segment2.ts"/><SegmentURL media="segment3.ts"/><SegmentURL media="segment4.ts"/>
……<SegmentURL media="segment136.ts"/></SegmentList></Representation></AdaptationSet></Period>
</MPD>

(2) 段模板表示:一个SegmentTemplate;

<?xml version="1.0" encoding="utf-8"?>
<!-- MPD file Generated with GPAC version 0.5.1-DEV-rev4736M  on 2013-09-12T09:20:37Z-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500000S" type="static" mediaPresentationDuration="PT0H9M54.00S" availabilityStartTime="2012-09-05T09:00:00Z" profiles="urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash264"><Period id="" duration="PT0H9M54.00S"><AdaptationSet segmentAlignment="true" maxWidth="1280" maxHeight="720" maxFrameRate="24" par="16:9"><Representation id="1" mimeType="video/mp4" codecs="avc1.42c01f" width="512" height="288" frameRate="24" sar="1:1" startWithSAP="1" bandwidth="1162074"><SegmentTemplate timescale="12288" media="BBB_512_640K_video_$Time$.mp4" initialization="BBB_512_640K_video_init.mp4"><SegmentTimeline><S d="61440" r="-1" /></SegmentTimeline></SegmentTemplate></Representation><Representation id="2" mimeType="video/mp4" codecs="avc1.42c01f" width="768" height="432" frameRate="24" sar="1:1" startWithSAP="1" bandwidth="1801786"><SegmentTemplate timescale="12288" media="BBB_768_1440K_video_$Time$.mp4" initialization="BBB_768_1440K_video_init.mp4"><SegmentTimeline><S d="61440" r="-1" /></SegmentTimeline></SegmentTemplate></Representation><Representation id="3" mimeType="video/mp4" codecs="avc1.42c01f" width="1280" height="720" frameRate="24" sar="1:1" startWithSAP="1" bandwidth="4487961"><SegmentTemplate timescale="12288" media="BBB_1280_4M_video_$Time$.mp4" initialization="BBB_1280_4M_video_init.mp4"><SegmentTimeline><S d="61440" r="-1" /></SegmentTimeline></SegmentTemplate></Representation></AdaptationSet><AdaptationSet segmentAlignment="true"><Representation id="4" mimeType="audio/mp4" codecs="mp4a.40.29" audioSamplingRate="48000" startWithSAP="1" bandwidth="33028"><AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" /><SegmentTemplate timescale="48000" media="BBB_32k_$Time$.mp4" initialization="BBB_32k_init.mp4"><SegmentTimeline><S d="239616" r="-1" /></SegmentTimeline></SegmentTemplate></Representation></AdaptationSet></Period>
</MPD>

段模板可以用动态变化的参数来描述段列表,不用像SegmentList那样将所有的文件列出来,简化MPD文件长度。
(3) 单段表示,由一个BaseURL元素,一个SegmentBase构成。不能有SegmentTemplate、SegmentList元素。

<Period><!-- Audio --><AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1"><Representation audioSamplingRate="44100" bandwidth="141962" codecs="mp4a.40.2" id="audio-und"><AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/><BaseURL>media-audio-und.mp4</BaseURL><SegmentBase indexRange="628-3599"> /* 指出段的索引信息,即sidx在上述URL代表的文件中的字节范围 */<Initialization range="0-627"/> /* 指出初始化信息在上述URL代表的文件中的字节范围 */</SegmentBase></Representation></AdaptationSet><!-- Video --><AdaptationSet maxHeight="534" maxWidth="1280" mimeType="video/mp4" minHeight="214" minWidth="512" segmentAlignment="true" startWithSAP="1"><Representation bandwidth="2850840" codecs="avc1.42C01F" frameRate="24" height="534" id="video-6" scanType="progressive" width="1280"><BaseURL>media-video-6.mp4</BaseURL><SegmentBase indexRange="693-3664"><Initialization range="0-692"/></SegmentBase></Representation></AdaptationSet></Period>

Segments构成Representation,每个Representation中的内容按照一定的规则被切分成一段段的的Segments;这些Segments可能共用一个URL,由Byte range指定范围或者使用不同的URL。同时,Segments还可以细分成SubSegments,SubSegments表示Segments中更细的Access unit。SubSegment index表示Subsegments的presentation time range和byte position,用户可以先获取index,再通过HTTP的byte range requests去请求相应的Subsegment。
        AdaptationSet中的码流内容一样,区别在于比特率,分辨率,声道数等等,不同的Representation用来描述这些差异,实际上的流媒体文件则存在于Segments段描述中。
        直播情况下,需要周期地去服务器更新MPD文件,服务器移除旧的Period,添加新的Period。  更新的周期由minimumUpdatePeriod字段指定,当 type = static 时,minimumUpdatePeriod属性不应该出现。

有这样一些注意事项:

1. 列表中可能存在多种内容一样,但编码格式等等不同的URL地址

2.DASH需要GstDashDemux->video demux/audio demux的连接,也就是说dash后面要接多个demux,有多少条流,就有多少个demux,并且demux前面还最好有队列,开销也是很大的。下面这段代码用于将每条流的pad外接。dash本身还是具有多个queue的demux。

  for (iter = demux->streams; iter; iter = g_list_next (iter)) {GstAdaptiveDemuxStream *stream = iter->data;if (!gst_adaptive_demux_expose_stream (demux,GST_ADAPTIVE_DEMUX_STREAM_CAST (stream))) {/* TODO act on error */}}

HLS稍有不同,HLS是GstHlsDemux之后,接一个比如TS/MP4 demux,TS/MP4 demux再分离出来A/V。

如上所述GstHlsDemux和GstDashDemux之后,不同分辨率的码流可以切换,轨道可以切换。一般说来,同一影片时间基数相同,切换方便,不同影片的流间切换需要技巧,也需要转换。 GstHlsDemux,GstDashDemux输出有多个,demux后的输出流也会是多条,这是一种多对多的关系。上报给客户会提到有多少种码流,这些码流的分辨率是多少。只有当前播放的流才能获取具体的轨道信息,其他的码流Pad由于没有创建demux处于Mute状态,作如下设计:

非直播情况下,第一次处理的period就是编号为0的period,直播时,更新MPD表时处理的period是初时获取的。GStreamer处理period下的所有AdaptationSet时创建流。
1. 取得一个AdaptationSet,创建GstActiveStream类型流stream并且初始化。设置stream的URL起始为0,cur_adapt_set为当前的set。
2. 找到最小带宽bandwidth的representation
3. 获取MIME TYPE,GST_STREAM_AUDIO,GST_STREAM_VIDEO等等,并将stream加入到active_streams链表中。
4. 为active_streams链表中每一条stream创建非ghost的srcpad, caps和GstDashDemuxStream对像,每一个AdaptationSet都有用gst_adaptive_demux_stream_new创建一个GstDashDemuxStream对象,它的pad将会是上述src pad。

GstAdaptiveDemuxStream *stream = g_malloc0 (demux->stream_struct_size);
stream->pad = pad;
stream->demux = demux;
stream->do_block = TRUE;
demux->priv->preroll_pending++;

将流对象将会被划设置成lock态,并且preroll_pending。
5. 创建下载线程gst_adaptive_demux_stream_download_loop,并将GstAdaptiveDemuxStream放到GstAdaptiveDemux也就是GstDashDemux的parent的next_streams链表中。
6. SEEK到即将要开始播放的位置。
也就是说,每一个AdaptationSet中都选择出了带宽最小的流加入到active_streams链表中并完成了准备。
下面看一下如何将src pad报告出去。
1. gst_adaptive_demux_prepare_streams配置prepared_streams, demux->prepared_streams = demux->next_streams;
2. 为每条流准备事件,设置成lock态,preroll处理完所有lock态的stream之后,preroll_pending为0时,将pad 开放出去。

static gboolean
gst_adaptive_demux_expose_stream (GstAdaptiveDemux * demux,GstAdaptiveDemuxStream * stream)
{gboolean ret;GstPad *pad = stream->pad;GstCaps *caps;if (stream->pending_caps) {gst_pad_set_caps (pad, stream->pending_caps);
……} else {caps = gst_pad_get_current_caps (pad);}
……/* Don't hold the manifest lock while exposing a pad */GST_MANIFEST_UNLOCK (demux);ret = gst_element_add_pad (GST_ELEMENT_CAST (demux), pad);GST_MANIFEST_LOCK (demux);return ret;
}

pad是手动添加的,但是元素element的pad移除可能是自动的,体现在下面几个时间:

1. 元素状态切换时,由PAUSE->READY时,移除持有的PAD。

2.元素所在BIN状态切换由PAUSE->READY时,移除子元素并且移除其PAD。

DASH的profiles

Profiles
Identifier Reference Section Comment
urn:mpeg:dash:profile:full:2011 ISO/IEC 23009-1 section 8.2 identifier for MPEG-DASH Full profile
urn:mpeg:dash:profile:isoff-on-demand:2011 ISO/IEC 23009-1 section 8.3 MPEG-DASH ISO Base media file format On Demand profile
urn:mpeg:dash:profile:isoff-live:2011 ISO/IEC 23009-1 section 8.4 identifier for MPEG-DASH ISO Base media file format live profile.
urn:mpeg:dash:profile:isoff-main:2011 ISO/IEC 23009-1 section 8.5 identifier for MPEG-DASH ISO Base media file format main profile.
urn:mpeg:dash:profile:mp2t-main:2011 ISO/IEC 23009-1 section 8.6 identifier for MPEG-DASH MPEG-2 TS main profile.
urn:mpeg:dash:profile:mp2t-simple:2011 ISO/IEC 23009-1 section 8.7 identifier for MPEG-DASH MPEG-2 TS simple profile.
urn:3GPP:PSS:profile:DASH10 3GPP TS26.247 section 7.3.3 identifier for 3GP-DASH Release-10 profile.
urn:dvb:dash:profile:dvb-dash:2014 HbbTV 2.0.1 HbbTV 2.0 HbbTV 2.0 DASH profiles.
urn:hbbtv:dash:profile:isoff-live:2012 HbbTV 1.5 HbbTV 1.5 HbbTV 1.5 DASH profiles

ISO BMFF On Demand——ISO BMFF点播

此profile能产生最佳的点播配置,以及带来播放器和服务器之间的最佳兼容性,有如下要求:

  • A single segment for each representation (one audio or video track per file).A/V独立,每个场景单独分断。
  • Subsegments are aligned across representations (GOP aligned fragments).相同场景的不同子片断以GOP方式对齐。
  • Subsegments must begin with a Stream Access Point (IDR/keyframe).子片断以SAP开始。
  • The segment is indexed using the Segment Index ('sidx').

ISO BMFF Main

所有的 DASH players 需要支持此 profile.

ISO BMFF Live

上面描述的 On Demand 和 Main 配置文件都需要在字节范围内请求 HTTP。 对于不支持字节范围的播放器或 CDNs,可以生成基于索引的片段文件以及使用 SegmentTemplate 的 MPD,如 DASH Live 。

加密DRM的一些知识:

DASH,HLS在加密流领域应用广泛:

AES(Advanced Encryption Standard)是最流行的加密技术之一。
        MSS(Microsoft Smooth Streaming)
        CENC(Common Encryption specification),视频既用cenc(AES-128 CTR),也可以用cbcs(AES-128 CBC)加密。CTR代表计数器模式;CBC代表密文分组链接模式。CENC意味着内容提供商仅需加密视频一次,并且任何解密模块都可以解密它。

主要的DRM技术:Apple FairPlay、Google Widevine和Microsoft PlayReady。
        在DRM中,密钥ID可以是公开的,与DASH或者HLS清单一起被发送到视频播放器,也可以在视频码流中插入一些包含独特信息的字节来描述此ID。
        加密密钥则存储在和DRM许可证服务器一起工作的KMS(密钥库)中。当客户端需要播放加密视频时,通过密钥ID向DRM许可证服务器请求解密密钥。如果DRM许可证服务器对请求(认证请求)认可,它将要求密钥库提供与该密钥ID对应的解密密钥。

CENC加密有两个标准文档
ISO/IEC 23001-7 : Common encryption in ISO base media file format files
ISO/IEC 23001-9 :Common encryption of MPEG-2 transport streams

DRM Decryptor sink caps枚举:

 application/x-webm-enc, original-media-type=(string)video/webm;application/x-cenc, original-media-type=(string)video/webm, protection-system=(string)1077efec-c0b2-4d02-ace3-3c1e52e2fb4b;application/x-cenc, original-media-type=(string)video/webm, protection-system=(string)edef8ba9-79d6-4ace-a3c8-27dcd51d21ed;application/x-cenc, original-media-type=(string)video/webm, protection-system=(string)9a04f079-9840-4286-ab92-e65be0885f95;application/x-webm-enc, original-media-type=(string)video/mp4;application/x-cenc, original-media-type=(string)video/mp4, protection-system=(string)1077efec-c0b2-4d02-ace3-3c1e52e2fb4b; application/x-cenc, original-media-type=(string)video/mp4, protection-system=(string)edef8ba9-79d6-4ace-a3c8-27dcd51d21ed;application/x-cenc, original-media-type=(string)video/mp4, protection-system=(string)9a04f079-9840-4286-ab92-e65be0885f95; application/x-webm-enc, original-media-type=(string)video/x-h264;application/x-cenc, original-media-type=(string)video/x-h264, protection-system=(string)1077efec-c0b2-4d02-ace3-3c1e52e2fb4b; application/x-cenc, original-media-type=(string)video/x-h264, protection-system=(string)edef8ba9-79d6-4ace-a3c8-27dcd51d21ed;application/x-cenc, original-media-type=(string)video/x-h264, protection-system=(string)9a04f079-9840-4286-ab92-e65be0885f95;application/x-webm-enc, original-media-type=(string)video/x-h265; application/x-cenc, original-media-type=(string)video/x-h265, protection-system=(string)1077efec-c0b2-4d02-ace3-3c1e52e2fb4b;application/x-cenc, original-media-type=(string)video/x-h265, protection-system=(string)edef8ba9-79d6-4ace-a3c8-27dcd51d21ed;application/x-cenc, original-media-type=(string)video/x-h265, protection-system=(string)9a04f079-9840-4286-ab92-e65be0885f95; application/x-webm-enc, original-media-type=(string)video/x-vp9;application/x-cenc, original-media-type=(string)video/x-vp9, protection-system=(string)1077efec-c0b2-4d02-ace3-3c1e52e2fb4b;application/x-cenc, original-media-type=(string)video/x-vp9, protection-system=(string)edef8ba9-79d6-4ace-a3c8-27dcd51d21ed; application/x-cenc, original-media-type=(string)video/x-vp9, protection-system=(string)9a04f079-9840-4286-ab92-e65be0885f95; application/x-webm-enc, original-media-type=(string)audio/mp4;application/x-cenc, original-media-type=(string)audio/mp4, protection-system=(string)1077efec-c0b2-4d02-ace3-3c1e52e2fb4b; application/x-cenc, original-media-type=(string)audio/mp4, protection-system=(string)edef8ba9-79d6-4ace-a3c8-27dcd51d21ed;application/x-cenc, original-media-type=(string)audio/mp4, protection-system=(string)9a04f079-9840-4286-ab92-e65be0885f95; application/x-webm-enc, original-media-type=(string)audio/opus;application/x-cenc, original-media-type=(string)audio/opus, protection-system=(string)1077efec-c0b2-4d02-ace3-3c1e52e2fb4b; application/x-cenc, original-media-type=(string)audio/opus, protection-system=(string)edef8ba9-79d6-4ace-a3c8-27dcd51d21ed; application/x-cenc, original-media-type=(string)audio/opus, protection-system=(string)9a04f079-9840-4286-ab92-e65be0885f95; application/x-webm-enc, original-media-type=(string)audio/mpeg; application/x-cenc, original-media-type=(string)audio/mpeg, protection-system=(string)1077efec-c0b2-4d02-ace3-3c1e52e2fb4b;application/x-cenc, original-media-type=(string)audio/mpeg, protection-system=(string)edef8ba9-79d6-4ace-a3c8-27dcd51d21ed;application/x-cenc, original-media-type=(string)audio/mpeg, protection-system=(string)9a04f079-9840-4286-ab92-e65be0885f95; application/x-webm-enc, original-media-type=(string)audio/webm;application/x-cenc, original-media-type=(string)audio/webm, protection-system=(string)1077efec-c0b2-4d02-ace3-3c1e52e2fb4b;application/x-cenc, original-media-type=(string)audio/webm, protection-system=(string)edef8ba9-79d6-4ace-a3c8-27dcd51d21ed;application/x-cenc, original-media-type=(string)audio/webm, protection-system=(string)9a04f079-9840-4286-ab92-e65be0885f95

HLS加密方式选择:

gstreamer hls-crypto类型是auto,包含'nettle', 'libgcrypt', 'openssl'三类模块。

Nettle是一个底层的加密库,密码库,是低级密码函数集合,是一个GNU软件包,GnuTLS使用Nettle。GnuTLS 实现了SSL,TLS和DTLS协议的安全通信。
        Nettle通过低级加密并为其提供一个简单而通用的接口。特别是,它不做算法选择、内存分配或任何I/O。因此,Nettle 旨在提供一个核心密码库,在该库上可以构建许多应用程序和上下文特定的接口。然后可以共享这些接口的代码、测试用例、基准测试、文档等,而无需复制Nettle的密码代码。

libgcrypt是一个非常成熟的加密算法库,也是著名的开源加密软件GnuPG的底层库,支持多种对称、非对称加密算法,以及多种Hash算法。Libgcrypt 依赖于库`libgpg-error’,是一个提供加密构建块的库。Libgcrypt库的所有接口(数据类型和函数)都在头文件gcrypt.h中定义。必须直接或通过其他一些头文件将其包含在使用库的所有源文件中。

OpenSSL是一个强大的,商用的,功能齐全的,开放源代码的加密库,应用程序可以使用这个包来进行安全通信。 整个软件包大概可以分成三个主要的功能部分:SSL协议库、应用程序以及密码算法库。采用C语言作为开发语言,OpenSSL支持Linux、Windows、BSD、Mac、VMS等平台,作为一个基于密码学的安全开发包,OpenSSL提供的功能相当强大和全面,囊括了主要的密码算法、常用的密钥和证书封装管理功能以及SSL协议,并提供了丰富的应用程序供测试或其它目的使用。

Gstreamer需要SSL/TLS协议,因此建议选择用OpenSSL。

其他

1. 下载流程:

gst_adaptive_demux_stream_download_loop
        调用demux_stream_update_fragment_info获取下一次要下载的uri的信息
                调用gst_adaptive_demux_stream_download_fragment 下载直到下载完成

2. GST_BIN_FLAG_STREAMS_AWARE是说当前bin能够处理其他元素的添加,删除pad操作,而不必等到元素发送no-more-pads信号。

3. SegmentTimeline:

SegmentTimeline 描述每个区段可用于播放的时间。每个 SegmentTemplate 会有一个 SegmentTimeline。S:S 描述可以取得区段的时间 (t 值)、区段的持续时间 (d 值),以及多少额外的连续区段具有此相同持续时间 (r 值) 的计数,也就是重复次数。 SegmentTimeline 中有一或多个区段。

<SegmentTimeline>
……
<S d="75333300" />
<S d="83333300" r="1" />
<S d="98833300" />
<S d="89166700" />
<S d="83333300" r="1" />
……
<S d="87666700" />
<S d="83333300" r="13" />
</SegmentTimeline>

4.DASH中presentationTimeOffset的作用:
        EPT:是分段最早的呈现时间,Earliest Presentation Time,指一个period中,各个分段segment相对于period的最早显示时间,相对时间较容易查找buffer时间BufferPosition。
4. anchor time:基准时间
        DASH有共享时间线,用来同步各条流,流中Segments自身也包含时间信息用于同步和无缝切换。如果period第一个Segment的EPT错误地设置为非0,可以通过presentationTimeOffset来纠正。

--- Period 1 ---
MSE.timestampOffset = Period@start = 0
BufferPosition(Seg 1) = MSE.timestampOffset + EPT = 0 + 0 = 0
BufferPosition(Seg 4) = MSE.timestampOffset + EPT = 0 + 6 = 6--- Period 2 ---
MSE.timestampOffset = Period@start = 8
BufferPosition(Seg 1) = MSE.timestampOffset + EPT = 8 + 0 = 8
BufferPosition(Seg 2) = MSE.timestampOffset + EPT = 8 + 2 = 10
/* 每个分段显示时间2秒,Seg5本来应该从第12秒开始,但此时EPT误设置不为0,导致时间错误 */
--- Period 3 ---
MSE.timestampOffset = Period@start = 12
BufferPosition(Seg 5) = MSE.timestampOffset + EPT = 12 + 8 = 20 /* 通过presentationTimeOffset来校正时间 */
--- Period 3 ---
MSE.timestampOffset = Period@start - @presentationTimeOffset = 12 - 8 = 4
BufferPosition(Seg 5) = MSE.timestampOffset + EPT = 4 + 8 = 12
BufferPosition(Seg 6) = MSE.timestampOffset + EPT = 4 + 10 = 14 

参考:https://websites.fraunhofer.de/video-dev/common-pitfalls-in-mpeg-dash-streaming/

从零开始成为GStreamer专家——MPEG-DASH HLS开发相关推荐

  1. 从零开始成为GStreamer专家——RTSP播放开发

    从零开始成为GStreamer专家--RTSP播放开发 RTSP不同于本地播放,也不同于http,它需要动态创建source的srcpad,不可以直接将source和typefind相连,涉及到的元素 ...

  2. 从零开始成为GStreamer专家——基于Windows的GStreamer从源码下载、编译到开发

    基于Windows的GStreamer从源码下载.编译到开发 本文介绍了在GStreamer下载方法, 使用过程中的部分依赖,以及在Windows上编译配置GStreamer 过程,为学习GStrea ...

  3. Live Streaming Protocol--三种主流的流媒体协议MEPG DASH,HLS,Smooth Streaming及其manifest 文件字段解释

    文章目录 MPEG DASH协议 Manifest.mpd 1. Manifest.mpd简介 2. Manifest.mpd字段 HLS协议 1. manifest.m3u8字段 2. ts文件 s ...

  4. MPEG DASH MPD文件字段解释

    转自:http://www.cnblogs.com/vleung/p/4162409.html MPEG DASH作为三大流媒体协议之一,诞生的目的是为了统一标准,因此是兼容SmoothStreami ...

  5. hls fifo_【正点原子FPGA连载】第一章HLS简介--领航者ZYNQ之HLS 开发指南

    1)摘自[正点原子]领航者ZYNQ之HLS 开发指南 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手 ...

  6. input自适应_【正点原子FPGA连载】第十一章基于OV5640的自适应二值化实验-领航者ZYNQ之HLS 开发指南...

    1)摘自[正点原子]领航者ZYNQ之HLS 开发指南 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手 ...

  7. 解锁HLS开发|Demo(1):ARM动态配置FPGA的自定义IP

    微信公众号:佛系入门ZYNQ图像处理 "狂浪是一种态度" "八卦HLS" 本次Demo目的及功能 本次Demo原理分析 HLS开发->源文件设计 HLS开 ...

  8. c语言代码大全_从学生到专家,C语言开发必读的8本书

    本号总结了在C语言实际开发中必读的8本书,当然这8本书并不能囊括开发的方方面面,但就作者亲身体验来看,这8本书确实每个C语言开发者都必须要读的书,并且是应该深入精读的书. C程序设计语言 相信大家都学 ...

  9. HLS 开发学习(五) 稀疏矩阵向量乘法

    文章目录 稀疏矩阵向量乘法 CRS数据结构 稀疏矩阵向量乘 Test bench 测试用例 优化 稀疏矩阵向量乘法 CRS数据结构 b即为a的CRS表示,值(values)数组保存矩阵中非零元素的值. ...

最新文章

  1. Manifest merger failed with multiple errors, see logs
  2. String.Split()函数
  3. 032_jdbc-mysql批量操作
  4. 妈妈帮×神策智能推荐,打造人性化智趣母婴服务
  5. 3D Human相关研究总结:人体、姿态估计、人体重建等
  6. 数据挖掘概念与技术12--数据立方体的计算和多路数组聚集详解
  7. [机器学习] Boosting算法2 --- GBDT
  8. 游国色天香中国馆有感
  9. 上下相机贴合对位计算公式_深圳贴合机生产家介绍;真空贴合机这些产品功能你了解多少...
  10. jquery的autocomplete在firefox下不支持中文输入法的bug
  11. 测试Live Write的发布功能
  12. 漫画微信小程序源码 全开源 商业版
  13. 测井 时深转换 matlab,时深转换操作步骤.pdf
  14. LED灯具检验标准与方法
  15. 【CF #807 Div2】A-D
  16. python英文文本情感分析_舆情信息浩如烟海?看看如何用Python进行英文文本的情感分析...
  17. 【替罪羊树及其应用】替罪羊树总结
  18. 中国电信北京研究院副院长陈运清:网络云化推进中技术和商业驱动场景探讨...
  19. 推荐几个免费的PDF to Word文件转换器
  20. 杜笙除镍树脂Tulsimer CH-90实际运用案例

热门文章

  1. centos6默认python2.6升级2.7
  2. 个人免签支付系统短信监控自动回调源码APP 实时自动回调!
  3. flex 电子表格实现
  4. Zemax操作12--简单牛顿望远镜
  5. 电子器件热设计知识点
  6. Photoshop制作转动的立方体魔方动…
  7. 为什么做好GMP符合性检查?看完你就知道了
  8. php获取条码秤称重后的数据,称重过磅数据可导出电脑表格显示以便财务统计的智能电子秤...
  9. Hanlp汉字转拼音使用python调用详解
  10. Small RTOS51 学习笔记(1)使用 RTOS 的好处