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. SAP RETAIL 特征参数文件(Characteristic Profile) III
  2. Oracle 的 DBMS_SCN 修正以及 SCN 的 auto-rollover 新特性
  3. QluOJ2018NewCode计算几何(寄蒜几盒)
  4. log4j2配置文件的故事
  5. 虚拟化技术原理与实现 pdf_多进程的实现原理-多道技术
  6. active server pages 错误 asp 0126_最终选型 Blazor.Server:又快又稳!
  7. HDU1250 Hat's Fibonacci 大数斐波那契数列
  8. linux中特殊字符的含义,Linux中的特殊符号以及特殊语法
  9. C#中的委托与事件[翻译]
  10. (数字IC)低功耗设计入门(六)——门级电路低功耗设计优化
  11. IBASE Read buffer invalidate when locked
  12. 【例题 8-13 UVA - 11093】Just Finish it up
  13. 8、mybatis中的sql映射文件详解(3)
  14. Hive map阶段缓慢,优化过程详细分析
  15. 通过ssh连接Termux
  16. canbus是什么意思_canbus.是什么意思
  17. Paper:可解释性之ICE/PDP《Peeking Inside the Black Box: Visualizing Statisti窥视黑盒内部:用个体条件期望ICE图可视化统计学习》翻译与解读
  18. JavaScript中的mouseover与mouseenter,mouseout和mouseleave的区别
  19. 2019年2月18日,异常作业
  20. 2023考研常识知识之五类数学有哪些区别

热门文章

  1. 如何从零配置高效的tensorflow python编程环境之VIM神的编辑器---DIY自己的VIM
  2. 【资源汇总】各种资源下载汇总
  3. 北京吉利大学计算机与科学,北京吉利大学与达内时代科技集团深度融合
  4. linux常用命令(详解)
  5. LV被查不合格 消费主义中国如何脱逃名牌陷阱
  6. 最强.NET SQLServer 操作类 SqlExecuteXY 源代码发布 使用教程文档
  7. java基础-ascii编码
  8. jdk的安装路径在哪_忘记jdk安装路径怎么办
  9. Dicom RTSS ROI Physical PropertiesSequence (3006,00B0)的定义和使用
  10. 同城艺龙2018秋招Java笔试之newInstance()--Binrry(冰蕊)