您当前位置: 首页 » 所有由

admin

发布的文章
所有由admin发布的文章

linux进程信号处理

最近在查coredump的时候,一直发现堆栈不完整。于是很好奇abort的信号默认情况下会如何处理。

网上查了一下,发现信号分为进程间信号多线程间信号

进程间信号,即进程之间可以互发信号,也可以进程内部某个线程来产生信号。由系统库提供支持。

多线程间信号,即线程之间互发信号,且指定具体线程来接收并处理。由pthread库提供支持。

由于coredump的抓取过程,应该没有做过特殊处理,因此使用的就是进程间信号。那么进程内,当某个线程执行某个代码时,产生了abort信号,信号会由谁来负责处理?实际测试的结果是由具体产生abort信号的线程来处理执行。

查了一下网上的解释,信号的处理,是由内核态准备切换回用户态时来处理,由于在态切换时,主动地插入了一个函数跳转指令,进而转为执行信号处理函数。因此由产生abort信号的线程来处理实现即简单,也符合逻辑。

由于是中断处理,这一点上可以看做和windows类似。

2020-06-16 | | [linux总结], unix编程环境学习

linux进程信号处理已关闭评论

未来的不确定,令人是喜或忧,细细品一品,又耐人寻味和受教匪浅

偶然的机会,听到了Sergi Vicente的歌,后来就渐渐开始关注他。听歌会影响一个人的心境,也能够间接的反应出,现阶段人的心境如何。

在听Sergi Vicente的歌时,偶然听到了Suite Intima这首歌(网上Suite Intima – Sergi Vicente即可听到)。

长达13分钟的歌,能听出至少三种情绪表达。差不多2-3分钟为一个篇章。单曲循环,一遍又一遍,前60%的音乐有着很强烈的共鸣。

当我年纪小时,我看到的社会就是:叔叔、阿姨、爸爸、妈妈、老师、同学、吃喝玩乐和无休止的学业。

踏入大学,“终于可以玩了的心态”和“我是万能的,我很牛X”伴随了我大学的前两年,大三大四开始,我无休止的焦虑、焦急和迷茫。

一方面,面领着继续升学还是踏入社会。另一方面,面领着家里总是絮絮叨叨的希望我回老家工作,一个人在“外面”(省外)太辛苦了,回老家才是父辈们根深蒂固的传统思维。

至于升学,因为自己小时候贪玩导致基础只是掌握不是很好,复习考研很吃力。尽管经过了一年多的备战,发现模拟题达标率还低于60%,心里就开始发慌发毛,开始自我怀疑,怀疑自己的选择是不是错误的。尽管后面还是和努力的去试图提高自己的模拟成绩,但内心的焦躁一点都没有缓解。

至于就业,我大学的专业是电子信息工程,从外界看这可是当年的热门专业,但站在我们自身看,虽然是热门专业,但就业面其实在当时有一定的首先。因为我们偏向于信号和硬件,而硬件和信号是中国的短板,其可就业的主要方向位于珠三角地区那就是欧美部分国家。出国?想多了,出国有很多种出法,有偷渡,也有拿绿卡去世界一流企业干一份技术含量高,收入不错的高精尖工作。但每年国内双一流学校往国外输送那么多人才,我们这种不入流的公办院校学生,还是只能喝汤。

介于就业和升学的双从压力下,我发现这样无意义的纠结下去两个事情都很难推进,于是我给自己定了一个plan a和plan b。

plan a:考研复习到大四上学习结束,如果模拟达标率还低于70%,直接转向找工作路线。

plan b:如果考研模拟题达标率成功稳定在70%,那么先参加考研,但找工作同步进行。只不过把重心适当的往考研方向靠。

因为心中有了一个较为清晰可行的思路,因此手中有粮,心中不慌。但可惜的是好景不长。很快进入大四,家里看状,也加紧了通过电话的说服教育,意图毕业后就回老家,考研的话家里支持的,就算考上研也还是期望回老家。

本来身心就在承受着巨大的压力,加之家里的不理解行为,让我一度陷入崩溃边缘。我认为我作为一名大学,我应该有我独立自主思考和选择的机会,只要这个选择不是特错大错的就好。

因为作为一名大学生,在大一新生的时候,碰巧遇到了《疯狂的石头》热播,导演和主演来我们学校给大家做交流,我逃军训期间偶然“闯入”这样交流会,见识到了和家里(长辈)“作斗争”不一样的思想。

因为在大一和大二期间,看到了熊丙奇写的两本书。

因为在大二,遇到了在摩根士丹利和华为的前辈们的思想开导。

因为在大三开始,看到了浙大强哥的一些讲座视频录像。

我对大学受教育的理解发生了一些变化,大学已经不再单纯追求成绩的地方,而是将人的思维、独立性、三观再塑养的最后一道关卡。因为接下来就是社会这个大环境。

所以呢,也和家里产生了很强的对立想法和对抗行为,自己当然需要进行下去的事情还需要继续。就这样持续了2个月左右(半个学期)。后来发现不对,这样不是办法,完全是徒劳且耗费精力的持久战,我自己最终会被拖跨。

所以我又改善了plan a和plan b。

新plan a:考研复习到大四上学习结束,如果模拟达标率还低于70%,直接转向找工作路线。但是现在本地(杭州)找,实在找不到,在考虑回老家找。

新plan b:如果考研模拟题达标率成功稳定在70%,那么先参加考研,但找工作同步进行。只不过把重心适当的往考研方向靠。工作杭州和老家一起找,如果考研成功读研,如果失败就看工作找的情况,老家工作不错回老家,杭州的工作不错回老家。

在新的计划里,会发现,针对在老家找工作的态度有强烈的差别化。为何这样?因为,考研一旦采取放弃的方式执行,那么我唯一还能搏一搏的就是在杭州找个工作,镀个金在回老家也来得及。

那么为何考研采取不放弃的方式还需要老家和杭州一起开找工作呢?因为研究生对父辈来说,看不见摸不着,也没有了解过是什么,更没有办法了解,万一考研成了,他们有可能会有强烈的疑惑,所以通过回老家找工作这条路堵住他们的嘴。万一考研成功,跑回来读研,也可以让旁人帮我说话,毕竟父辈嘛,永远都是别人家说的话比自己女说的话更可信,你懂得(中国式家庭)。

后来奈何家里怎么“骚扰”和“干涉”,我心态就是相对平静和安稳。

来准备毕业了,即将毕业了。因为本人基础实在太差,心虚,加上精力分散过于厉害,考研没参加,放弃了。

但换而来之的是,工作出奇的好找。班上的很多同学都还在苦恼的时候,我已经随便面试就能成,而且面试机会差不多是至少20来个,安排的满满当当,连饭都来不及吃。当大家都在一片哀嚎时,我似乎有点另类。当时还觉得有点奇怪为何这样,可能是我真的幸运?

直到活到现在,一次次回首去总结经验和寻找原因,我才发现。心态很重要,规划也很重要。

心态首先平和,能够让自己有更广的机会,心态的重整做,能够让自己有更好的环境适应性,心态的细粒度微调,也是让自己的规划能够随着事态发展而在不较大改变大方向的前提下,适当的适应当下。

规划,有规划意识,是产生规划的前提。紧接着心态与规划行为的相辅相成作用,便可行程可行又相对灵活且大方向变化微乎其微的规划,结果也才能尽量达成。

很多事不是能够一气呵成的,我也是踏入社会这多些年,才一点一点的搞清楚。要说幸运的话,只是我刚开始的行事风格和目标有较大概率符合达成目标条件罢了,一个瞎猫碰到死耗子情况而已。

正因为未来有着很多的不确定,才会让人着迷,回过头去想一想,其实也不见得有这么多不确定,只是因为没有经历过,缺少有效的办法去发现和分析而已。人生就像一坛酒,有些酿出来的那就是醋,而有些只是口感一般的酒;再有一些就是口味不错,回味无穷的好酒。其原因还是酿酒过程中的一些关键性因素把握罢了。

2020-05-09 | | [心理学], [我的认知系列], *生活*, 思考

未来的不确定,令人是喜或忧,细细品一品,又耐人寻味和受教匪浅已关闭评论

关闭win10默认的音效增强

可能是驱动的原因,也可能是win10自带音效增强做了改变,最近更新系统后,总发现声音不对,低频听似被增强,但事实上有很重的混响情况。

查来查去发现DTS和驱动自带的音效并没有启动,后来就想到会不会和win10自带音效是否有关,结果发现确实有关。具体步骤为以下。

打开声音配置界面如图
找到对应的声音设备,并打开属性

勾上禁用所有声音效果,即可关闭默认的音效,让该设备声音输出恢复到较原始的情况。

2020-02-24 | | *生活*

关闭win10默认的音效增强已关闭评论

编译freeswitch踩的那点坑

由于虚拟机里面装了ubunutu 18,本来想直接装freeswitch的deb报,进行方案快速验证和freeswitch学习。结果,按照官方的步骤去执行,发现源有问题。

接着就进入了苦逼的编译过程,说实话,对freeswitch的官方文档表示迷惑,不是很习惯文档中描述的内容跳来跳去的样子。后来找来找去,就零零散散的参考按照了以下几个文档进行下去,基本采取默认配置,并没有作为其他配置修改

https://freeswitch.org/confluence/display/FREESWITCH/Installation
https://freeswitch.org/confluence/display/FREESWITCH/Ubuntu#Ubuntu-InstallfromRepo
https://freeswitch.org/confluence/display/FREESWITCH/Linux+Quick+Install+Guide#LinuxQuickInstallGuide-GenerateInstallationandConfigurationFiles

首先先说一下步骤:

安装依赖

apt-get install git-core subversion build-essential autoconf automake libtool libncurses5 libncurses5-dev make libjpeg-dev liblua5.3-dev

apt-get install libcurl4-openssl-dev libexpat1-dev libopus-dev libgnutls-dev libtiff4-dev libx11-dev unixodbc-dev libssl-dev python2.6-dev zlib1g-dev libzrtpcpp-dev libasound2-dev libogg-dev libvorbis-dev libperl-dev libgdbm-dev libdb-dev python-dev uuid-dev libpq-dev libsndfile-dev

sudo apt-get install gawk

update-alternatives --set awk /usr/bin/gawk

下载freeswitch代码

FSfile=$(curl -s https://files.freeswitch.org/releases/freeswitch/ | grep -oE “freeswitch-[0-9].[0-9].[0-9]*.-release.tar.bz2″ | tail -n 1) && echo Downloading $FSfile && curl https://files.freeswitch.org/freeswitch-releases/$FSfile | tar -xj && mv ${FSfile/.tar.bz2//} freeswitch

编译x264

这是为了启动mod_av模块的时候,而进行的准备工作,以下命令行为:

./configure --enable-static --prefix=/usr --enable-pic

 make ; make install 

编译ffmpeg

如果不编译ffmpeg,或不安装libavformat-dev就进行执行./configure,又刚好开启了freeswitchmod_av,那就会出现You must install libavformat-dev to build mod_av. Stop错误。

在网上查一同,会发现需要编译libav,事实上却被大坑了一把。这主要还是由于ffmpeg与libav的关系有关。

libav是从ffmpeg拉出的一个分支,网上对libav说法很多,又说libav是从早期版本拉出来,也有说后来libav已经和ffmpeg的master保持同步等等。

但真实去编译的时候,发现了一个巨坑,也就是freeswitch报错AVFormatContext中不存在url成员。到ffmpeg和libav官网上一查。发现最新版本的libav确实没有这个变量,而ffmpeg 4.x的文档里有。果断改成编译ffmpeg。

另外还要喷一下libav的官方文档,各种详细说明藏的非常深。。。

下好ffmpeg 4.x的源代码后,开始编译

./configure --enable-shared --enable-gpl  --enable-libx264 --enable-pic

make && make install

编译libk

 git clone https://github.com/signalwire/libks.git  

 cd libk  

 cmake . 

 make ; make install 

编译signalwire-c

git clone https://github.com/signalwire/signalwire-c.git

 cd signalwire-c 

 cmake . 

 make ; make install 

mod_lua编译不过

尽管安装了lua的开发库,但还是会出现找不到lua头文件的情况,找到

/src/mod/languages/mod_lua/Makefile

并找到如下行

DEFAULT_INCLUDES = -I. -I$(top_builddir)/src/include -I$(top_builddir)/libs/esl/src/include -I$(top_builddir)/libs/xmlrpc-c

修改成

 DEFAULT_INCLUDES = -I. -I$(top_builddir)/src/include -I$(top_builddir)/libs/esl/src/include -I$(top_builddir)/libs/xmlrpc-c -I/usr/include/lua5.3 

并到/usr/lib/x86_64-linux-gnu下

对liblua.so做个软连,即

ln -sf liblua5.3.so liblua.so

出现implicit declaration of function ‘ks_json_get_object_cstr’; did you mean ‘ks_json_get_object

由于版本不一致引起的,freeswitch、signalwire-c和libks版本不要一致,需要换版本。由于我用的freeswitch是1.10版,所以直接用9月份附近的这两个库就没问题了。

切换libks与signalwire-c版本后cmake不过的问题

直接从github上下载release的1.3.0版本,出现了cmake不过的情况:

— cotire 1.7.10 loaded.
Platform is linux
Build type: Debug CXX Flags:
Install prefix: /usr
LibKS Version 1.3
CMake Error at CMakeLists.txt:291 (string):
string sub-command REPLACE requires at least four arguments.
Found UUID setup target at imported location: /usr/lib/x86_64-linux-gnu/libuuid.so

看了一下cmake的配置文件,报错的位置主要是为了生成一个changlog文本,直接注释掉这行即可

#string(REPLACE "\"" "" CHANGELOG ${CHANGELOG})

阿斯顿

注意点

由于configure在执行的时候,会检查大部分依赖是否存在,但仅对关键依赖进行报错,且输出的检查内容太多以至于没有那么多耐心去看。

因此在出现configure不报错,make期间有某个mod编译失败的话,那就必须要用排错后,再次执行configure在进行make,反正就是各种复杂和扯淡。

编译完成后的运行

由于freeswitch会加载相应的mod,还有配置文件,所以需要执行一下make isntall;假设在configure阶段没有指定具体的prefix,就会默认安装到/urs/local/下。如果不需要这样,可以明确指定perfix位置。

运行freeswitch,执行 ./freeswitch即可

2020-01-20 | | VOIP, 音视频_图像相关

编译freeswitch踩的那点坑已关闭评论

srs-bench代码整理及理解

废话不多说,直接上图,以下是对srs-bench主要模块的一个梳理:

srs-bench支持对srs进行压测,其支持的范围有:

rtmp推流

rtmp拉流

hls拉流

http请求

hls拉流:

hls的拉流是,先产生一个http请求并拉去m3u8文件,解析后并顺序请求ts文件,当请求完毕后,下载任务挂起,一般挂起时长为当前模拟播放的ts文件的duration大小。

等挂起被唤醒后,再次请求m3u8文件,并更新未下载的ts文件列表后,开始请求ts文件。若本次更新的m3u8没有发生变化,那么将进行再次挂起,挂起时长不大于当前模拟播放的ts的duration。

http请求:

首先对某个url进行请求,请求之后将会产生挂起,挂起时长主要有进程启动时的入参决定。

rtmp推流:

rtmp推流进程启动时,首先会和srs在rtmp协议上进行协商,协商完成后,会读取入参时指定的flv文件。并按照当前flv tag和下一个flv tag的时间差挂起数据发送任务。

但这里需要注意的是,如果rtmp推流的压测里指定了2个以上的并发,但又由于srs-bench只支持一个flv文件输入,那么文件打开的次数会很多次,并且读取的flv数据在协程中未共享的,因此在该测试中,这一块可以改经一下,毕竟单线程的任务来说,不存在加锁问题,因此也就可以考虑是否做到一次性将数据读到内存里,所有协程共享数据发送;以此来提高测试程序的执行效率。

毕竟协程在io上不是强项。

rtmp拉流(非fast):

对于非fast的rtmp拉流,其整个协议过程是完整的rtmp client。只不过对拉下来的流不做解码等处理,仅仅是针对协议上做一些校验和处理而已。

rtmp拉流(fast):

类似非fast的流程来说,只是收到的数据不再做rtmp协议的校验了。

2019-12-12 | | SRS, 音视频_图像相关

srs-bench代码整理及理解已关闭评论

go环境在vs code中的几点坑

由于某些不可抗拒的原因,要搞go,事实上我是非常抵制,主要原因还在于go的开发环境等都不够成熟,另外也没有必要非要用go,除了由于python的gil性能问题意外,其实c、c++、python就已经足够满足大部分开发需求了。就连音视频部分的绝大部分都已经能够胜任。

唉,在vs code中虽然配置看上去虽然简单,但由于go语言本身坑爹的编译环境加之vs code整体性不如vs,因此还是遇到不少坑。

坑爹一:在使用go调试代码时用到了dlv,非调试运行环境也最好用dlv,不要用code runner。

具体表现为,使用start without debug,不要使用run code。由于在gopath的问题上,code runner在go开发环境上本着能坑死一个算一个的目标,让人哭笑踢飞。

持续更新中…….

2019-11-22 | | [奇葩类]求上进系列, 编码技巧

go环境在vs code中的几点坑已关闭评论

大小端安全简单访问技巧


bool srs_is_little_endian()
{
// convert to network(big-endian) order, if not equals,
// the system is little-endian, so need to convert the int64
static int little_endian_check = -1;

if(little_endian_check == -1) {
union {
int32_t i;
int8_t c;
} little_check_union;

little_check_union.i = 0x01;
little_endian_check = little_check_union.c;
}

return (little_endian_check == 1);
}

通过上面代码片段可发现little_check_union的大小只有4个直接,通过访问最后一个字节来判断当前平台(软件+硬件平台)大小端情况。

同时也可以利用union来进行访问,这样的访问方式较直接安位操作来说简单性能差一些,但也只一种较为简便和安全的做法。(虽然不是绝对安全的做法)

2019-08-05 | | 思考, 数据结构 & 算法, 编码技巧

大小端安全简单访问技巧已关闭评论

写代码中少用或避免用的一些技巧和方法

在写代码的时候,有一些技巧和方法已经快成为成为了众矢之的,主要还在于代码的可阅读性,以及易错性上。

被列为经典的几种方法或技巧中有一些还是能用尽量少用:goto、递归、状态机。

goto

写过汇编的人都知道,汇编改变指令执行地址的方法里,除了call/ret,还有大量的jmp/sjmp来构成一个程序,如果仅仅使用call/ret来写,有时候代码会变得非常臃肿,而且让本来就难以理解的汇编变成更难阅读的代码,所以就会用jmp/sjmp来改变指令执行的地址。当然这只是抛砖引玉,在汇编里改变指令执行地址可不仅仅这两对指令,还有很多其他指令和方法。

而goto是我在学c语言的时候接触到的,c++也依然部分支持(具体看编译器和相应语言标准)。goto更像是汇编中变成思维的一种移植,类*inx系统的内核代码里也拥有大量的goto使用。

在面向过程变成里,使用goto似乎并没有太大不适,而且也能在一定程度上减少代码规模。但goto若用的不好,带来的效果适得其反。而且容易使得代码逻辑变得极其复杂,非常的绕思维。

goto在短小精干的代码里,可以较少的带来阅读和易错现象,而且要把goto用的好,用的巧妙,还非常考验写代码的人如何编排代码流程和排版。

若没有过硬的逻辑思维能力和计算机式的思维能力,goto能避免最好避免,尤其是在写一些对代码体积和性能要求不是太高的情况下。

代码的性能和体积其实可以通过其它方式优化,未必非要这样。

递归

在数据结构和一些基本算法的教学里,递归是用的最频繁的。因为一些解题思路用递归来执行比较接近人类的思维方式,更容易理解。

栈帧的维护和执行,也是通过递归的方式进行的;可见递归的重要性。但是递归还存在容易让栈空间溢出,以及无限递归的出现,同样也存在一些不便于理解代码的情况。因为每一次递归函数的重入,都会使用新的栈帧对象,导致局部变量不是同一个的现象,这恰恰很有可能会让人在无意间错会递归的过程。

若不是解决问题的模型比较接近递归或代码短小精干的情况下,能用别的方式化解递归,最好通过其它方式。

状态机

状态机是一个基本的原型机或记录器,要从时间的角度出发讨论,状态机应该最先出现在高频模拟电路里,一些信号同步机制与触发应该是最接近状态机思维。

只不过后面称做状态机的都是从数字电路开始,状态机在设计门电路时,是最好用的一种分析工具或辅助工具。但在协议栈、驱动、直接和硬件交互的代码里,往往有着很多的状态机。

状态机由于仅仅是表征一种状态跃迁并联系成一个系统的工具,并未对状态跃迁的规则做约束,因此状态机很有可能会被设计的非常复杂,详情可以参考协议栈代码。若是过于强调状态机的特性,在写一些复杂度较高的策略模型时,往往是容易简单问题复杂化,甚至力不从心。

建议将状态机解耦,改为状态化就好。接触每种一状态之间的耦合度,会让代码较为简单些,如非常强调性能,可以通过其它方式解决。

2019-07-01 | | [linux总结], unix编程环境学习, 思考, 编码技巧

写代码中少用或避免用的一些技巧和方法已关闭评论

RUDP的多分支选择

先来说说什么是RUDP,RUDP全称Reliable User Datagram Protocol,译文为可靠的UDP传输。

准确的说RUDP应该是一种概念,而不是某个开源库。他是利用UDP无连接的特性中的优点,通过模拟TCP的可靠性传输来实现。

换句话说,从OSI模型或常规的四层网络模型的角度说,本质上就是一个UDP协议的通讯机制,只不过认为的加入了TCP中的握手、重传等功能。虽然有相应的标准规范给了RUDP一个身份,但可以看做一种应用层协议。

RUDP概念实现的协议有很多,由最初的RUDP库,也有后来用的较多的UDT,也有现在的SRT等等。

UDT:起初在做P2P网络传输的时候,当时用的是UDT(已经停更很久了),现在网上放眼望去也出现很多RUDP概念的实现。这个库据说是,当年提出RUDP概念的作者所做,由于是半路参与P2P传输这块,也就无从得知为何要选择UDT,但后来从UDT的写代码来看,UDT实现的侧重点在于如何模拟TCP进行可靠的传输,并尽量处理好UDP的分组问题,对于传输的效率方便考虑并不是考虑很多。在非实时和大吞吐量传输中还是具备一定的优势(尤其是可靠性方面)。

RUDP(非开源):这是当前接触到的,看着代码不太像网上某个具体的库,而很像多个库中的实现理论依据“粘合”出来。这个代码与业务的耦合性非常高,不是一套纯粹协议栈的代码,其中比较“机智”的利用了业务特性来节省掉纯协议上的可靠性实现,代码看上去要去UDT在协议实现部分会“短小精干”不少,估计在所谓“性能”上应该会比UDT好一些(cpu执行效率,因为要传输音视频数据),但这个库存在的问题实际上要比“UDT”严重很多,因为这套代码并没有在传输上做太大优化,导致在需要做稍微大一点的吞吐时,数据经常被拥塞(堵住)。随着现在带宽越来越大,小运营商也越来越让人抓狂,加上网络承载数据逐渐增加,这套RUDP代码已经不够用了,除了所谓的CPU执行效率较高以外,网络传输效率低的可怜,对带宽的有效利用率非常低。

SRT:从官方的README来看,并通过和最后一个版本的UDT代码做了比较之后发现,事实上SRT的代码确实源自UDT,并且在这个基础上做了ARQ,Buffer控制的改进,加密功能。

并没有完完整整的去看并理解SRT,仅从代码差异上的走马观花式的来看,SRT确实有着跟灵敏的丢包感知和处理,这也是ARQ的一个特性之一。同时在Buffer的控制上,增加了Buffer的双端反馈机制。主观上理解,SRT的吞吐能力应该会比原始的UDT代码弱一些,并且带宽的有效利用率可能会差一些。因为侧重点在于实时性,因此可能会对带宽的有效利用率做出一定的牺牲,在P2P传输场景下,可能还好说,但对于P2SP的情况下,可能会对服务器带宽的需求有一定的增加。

尤其是这个buffer控制,很耐人寻味,没有详细看,不是很清楚有没有特意做了数据的分段/分组优化。

后续还需要认真看看SRT的代码,详细的了解一下整个机制的发挥情况。不过看官方文档的介绍,给人感觉借鉴了不少RTCP/RTP的协议特点。不晓得有没有拿了一些RTSP,毕竟三者是可以放在一起做组合的。

2019-06-10 | | 未分类

RUDP的多分支选择已关闭评论

Why We Created SRT and the Difference Between SRT and UDT

Article Form :
https://www.haivision.com/blog/broadcast-video/created-srt-difference-srt-udt/

Editor’s Note: This post originally appeared on the GitHub Wiki for SRT. It has been slightly modified for formatting. 

Some people have asked us why we’re using the UDT library within our SRT protocol. Actually, some people claimed that SRT is just a slightly modified version of UDT and that UDT is known to be useless for live video transmission. Guess what, the latter is true. UDT has been designed for high throughput file transmission over public networks. However, SRT is far from being a slightly modified version of UDT. I’ll get into the details, but will start with a little bit of history.

Haivision has always been known for lowest latency video transmission across IP based networks — typically MPEG-TS unicast or multicast streams over the UDP protocol. This solution is perfect for protected networks and if packet lossbecame a problem, enabling forward error correction (FEC) fixed it. At some point we were getting questioned as to whether it would be possible to achieve the same latency between customer sites in different locations, between different cities, countries or even continents.

Of course it’s possible with satellite links or dedicated MPLS networks, but those are quite expensive solutions, so people wanted to use their public internet connectivity instead. While it’s possible to go with FEC in some cases, that’s not a reliable solution, as the amount of recoverable packet loss is limited, unless you accept a significant amount of bandwidth overhead.

After evaluating the pros and cons of different third party solutions, we found that none satisfied all our requirements. The lack of insight into the underlying technology drove us to the the decision to develop our own solution, which we then could deeply integrate into products. That way, it would become the “glue” that enables us to transmit streams between all our different products, locally or across far distances, while maintaining our low latency proposition.

There were a few of possible choices to consider:

  • The TCP based approach. Problem for live streaming: Network congestion, too slow packet loss recovery.
  • The UDP based Approach. General problem: Packet lossjitter, packet re-ordering, delay
  • Reliable UDP. Adds framing and selective retransmit.

Having had a history with UDT for data transmission, I remembered its packet loss recovery abilities and just started playing with it. Though not designed for live streaming at all, it kind of worked when using really big buffers. I handed it over to one of our extremely talented networking guys in the embedded software team (thanks, Jean!) and asked him whether he’d be able to make this a low latency live streaming solution. I didn’t hear anything back for quite a while and had almost lost my hope, when he contacted me to tell me he had to rewrite the whole packet retransmissionfunctionality in order to be able to react to packet loss immediately when it happens and that he added an encryption protocol, which he had specified and implemented for other use cases before. Nice 🙂

We started testing sending low latency live streams back and forth between Germany and Montreal and it worked! However, we didn’t get the latency down to a level we had hoped to achieve. The problem we faced turned out to be timing related (as it often is in media).

Bad Signal

What happened was this: 

The characteristics of the original stream on the source network got completely changed by the transmission over the public internet. The reasons are delay, jitterpacket loss and its recovery on the dirty network. The signal on the receiver side had completely different characteristics, which led to problems with decoding, as the audio and video decoders didn’t get the packets at the expected times. This can be handled by buffering, but that’s not what you want in low latency setups.

The solution was to come up with a mechanism that recreates the signal characteristics on the receiver side. That way we were able to dramatically reduce the buffering. This functionality is part of the SRT protocol itself, so once the data comes out of the SRT protocol on the receiver side, the stream characteristics have been properly recovered.

The result is a happy decoder: 

Good Signal

We publicly showed SRT (Secure Reliable Transport) for the first time at IBC 2013, where we were the only ones to show an HEVC encoded live stream, camera to glass, from a hotel suite outside the exhibition directly onto the show floor, using the network provided by the RAI. Everybody who has been at a show like this knows how bad these networks can get. And the network was bad. So bad that we expected the whole demo to fall apart, having pulled the first trial version of SRT directly from the labs. The excitement was huge, when we realized that the transmission still worked fine!

Since then, we added SRT to all our products, enabling us to send high quality, low latency video from and to any endpoint, including our mobile applications. Of course there were improvements to be made and the protocol matured on the way. Until NAB 2017, where we announced that SRT is now Open Source.

You can learn more about SRT at the SRT Alliance website here.

To view the SRT on GitHub and start contributing to this open-source movement, click here!

2019-06-10 | | udt, 网络协议, 音视频_图像相关

Why We Created SRT and the Difference Between SRT and UDT已关闭评论

迁移站点完成

由于之前主机提供商的openvz系列已经不再提供续费服务,后来一直找到一个相对稳定的提供商,下单后限制了几天,偶然发现刚好只有这个主机可以正常访问,另外一个备份服务器已经ping不通了。

然后就趁openvz主机还有几天时间,果断把整个站点都迁过来。基本还算顺利,目前就看这个刚成立的提供商会不会跑路了。

恩,先这样。

2019-06-07 | | *生活*, vps总结

迁移站点完成已关闭评论

【webrtc、gclient】cpid更新失败代理新的配置方案

首先按照原先的配置方案如下:

1. 设置http_proxy和https_proxy环境变量

2. 设置winhttp代理

3. 配置git代理

但在执行gclient自身更新时,总是发现cipd更新失败。简单跟踪了一下cpid,发现cpid的更新有两种,第一种是cpid自身自动更新,另一种是通过执行bootstrap来更新cpid。
cpid是使用go写的,虽然网上一堆教程说配置了http_proxy之后就可以等等,但这其中cpid存在一个问题,即在进行https请求时,会对证书做校验,若https_proxy配置的代理是一个https真实代理服务器,那么cpid做校验时会失败,具体未看代码,估计webdav执行过程中需要用到https中的证书做登录校验。

至于对cipd的更新处理方式为:

因此将https_proxy有意配置成http服务器,即可破。这会让cipd自更新时强制通过ensure方式进行更新

同时在其他一些脚本执行时,似乎用到了类似原先的csript,因此最好在ie代理时也配上相应的代理服务器地址。这样就可以正常更新gclient了。

2019-01-15 | | shell, windows-shell, 音视频_图像相关

【webrtc、gclient】cpid更新失败代理新的配置方案已关闭评论

【ios、x264】将静态库打包成动态库,链接时的text relocations错误

最近在ios上出现将多个sdk放到一个app时,有各种开源静态库冲突的问题;于是考虑将自己用到的库进行打包成动态库版本,以此解决冲突问题。

在进行打包成动态库时,发现x264问题最大。打包出来的库在链接期出现text relocations错误,网上找了以后发现基本都是进行忽略这个错误,事实上这个错误忽略了没用,app启动时还是会出现相应的crash。

换了几个版本的xcode进行测试,发现x264编译会出现不同情况的告警和错误,根据底部罗列的参考文章,估计xcode的编译器可能也有一些bug。

后来模仿android上的编译方式,在x264里加入了–enable-pic和–disable-asm顺利编译通过,但由于osx和xcode版本的因素,模拟器上的并没有编译出来,仅仅编译了armv7和arm64。

 

参考文章:

MacOSX下编译linphone(text-relocation错误说明)

libxxx.so- text relocations问题的终极解决方案(android)

Linker error when using incremental builds on iPhone

Android Gradle编译so库或运行时出现 text relocations 崩溃的正确解决方法

2018-06-15 | | [linux总结], unix编程环境学习, 编码技巧, 音视频_图像相关, 音视频编解码

【ios、x264】将静态库打包成动态库,链接时的text relocations错误已关闭评论

【设计模式】对代理模式的几点理解-

设计模式一直给我的感觉都是天书一样,一方面理解起来困难。另一方面书上的解释也较为枯燥,况且现在也还有很多号称设计模式大神的出现,也可能间接的让大家对同一个模式有了各种千奇百怪的理解。

设计模式这个东西出现初衷本来就是解决工程问题,而在解决工程问题时,每个人的角度不同,观点也就不同,并且在《head frist 设计模式》中,作者也强调过,没有任何一种模式的选择和使用是正确或者错误的,只有适合与否。同时对设计模式理解有偏差,甚至初学者也才会去讨论某某模式好,某某模式如何。对设计模式理解较为全面,工程经验较为丰富的人,只会说某种模式用起来较为自然。

代理模式可以的重点可以看作主要是屏蔽了实现细节,同时也对任务执行做了一个中转。让两个模块之间进行解耦。

例如一个消息队列的实现,对于消息队列来说,实现可复杂可简单。为了让消息队列的使用者能够更清晰的了解如何使用,首先需要对消息队列的一些内置方法进行屏蔽,在C++中,继承是无法做到这一点的,所以只能通过包装的方式来实现。

因此就产生了代理类来将消息队列的实现类进行包装,让消息队列的使用者更加关注与如何使用,让消息队列的实现者来关注如何实现,而对于代理来说,仅仅需要关注如何流转数据和流程即可。

2018-03-07 | | 思考, 程序结构/程序构架, 编码技巧

【设计模式】对代理模式的几点理解-已关闭评论

【C++11,自动变量,迭代】c++11下不同for循环的差别

先看如下代码片段

#include <vecotr>
#include <string>

#include "boost/algorithm/string/split.hpp"
#include "boost/algorithm/string/classification.hpp"
#include "boost/algorithm/string.hpp"

std::vector vStrArray; //里面存着一堆字符串,其中有一个字符串是这样的: " a.kbasdasdsad"

for (auto a : vector)
{
  boost::trim(a);
}
#include
#include

#include "boost/algorithm/string/split.hpp"
#include "boost/algorithm/string/classification.hpp"
#include "boost/algorithm/string.hpp"

std::vector vStrArray; //里面存着一堆字符串,其中有一个字符串是这样的: " a.kbasdasdsad"

for (std::vector::iterator a = vector.begin();
     a != vector.end();
     ++a)
{
  boost::trim(*a);
}

编译环境是vs 2015 update 3
分别执行完以后会发现,A代码片段没有任何变化,B代码片段的” a.kbasdasdsad”变成了”a.kbasdasdsad”。

单步的时候发现,a变量在A代码片段中,实际上是已经对被修改了。后来网上查了几篇资料,怎么也没有找到对auto的详细说明。加上c++ 11每个编译器实现可能存在一定的差异,因此只能认为,在auto修饰的for循环里,变量使用了写时复用的方式来处理。
如果要对vector里面的值进行修改,还是只能使用最原始的迭代器方法。

2018-01-03 | | 编码技巧

【C++11,自动变量,迭代】c++11下不同for循环的差别已关闭评论