编译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即可

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协议的校验了。

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开发环境上本着能坑死一个算一个的目标,让人哭笑踢飞。

持续更新中…….

大小端安全简单访问技巧


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来进行访问,这样的访问方式较直接安位操作来说简单性能差一些,但也只一种较为简便和安全的做法。(虽然不是绝对安全的做法)

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

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

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

goto

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

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

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

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

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

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

递归

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

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

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

状态机

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

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

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

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

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,毕竟三者是可以放在一起做组合的。

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!

迁移站点完成

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

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

恩,先这样。

认知成长=目标达成/失败=想法+行动

每一次遇到一个槛,都会想着通过努力迈过去,但从来没有得到过任何正确的点拨。于是乎,走了不少弯路。

弯路走的多了,有时候认知也就渐渐清晰了,但也心中的锐气和坚定也被挫掉了不少。不免有想放弃的想法,负面情绪一上来了,就不免会去反思,越反思越烦恼,久而久之形成了扭头往回退的想法。

2019年初,其实对生活充满的憧憬和向往,当然这里面有一些自欺欺人的成分,因为我对我的现状不满,我对我开始的懒惰不满。2019年春节,心怀喜悦回老家过年。在老家待了半个月不到,人也开始有了一些想法。

说我想法之前,先说一说我的理想。

  • 读大学时,心里有个梦想,就是成为站在技术顶端的人。即成为专家
  • 步入工作后,一定想买房,扎根在外面,因为老家实令人太伤感了
  • 买了房之后,一心想多赚点钱,早点退休。买辆旅行车,开这车周游世界

而我现在的状态也好,理想也罢。正是想摆脱“工作”的牢笼,想出去走走,见见世面。同事也“得益于”房价暴涨,买的房子增值很快,自己也成为数字游戏中的小康水平。

今年回到老家,感受着老家生活的慢节奏,悠闲(其实对于在老家的一部分人来说,应该是属于闲的蛋疼),消费不高;心理一下子膨胀了起来,似乎自己也给自己突然找到了一个社会位置一样。随着在老家休假的时间越久,心理也渐渐的默认了,这样的悠闲生活是我想要的,后来心理盘算着,是不是把杭州的房子一卖,拿着钱回来也能过上短暂的无忧无生活了。后来心理一盘算感觉不对,杭州的房子不能卖,要是在老家待腻了那岂不是我没退路了?所以左想右想么,心理一盘算么感觉这笔买卖还不错,于是呢就准备着手去看看老家的工作好不好找,薪资水平如何等等。

随着精力的渐渐投入越来越多,对老家的了解也渐渐清晰。焦虑就越重,一方面看到了老家就业的不公平,另一方又舍不得杭州这边已有的积累。所以心态一时间就炸的体无完肤,同时也对周围的人造成了一定的影响。

后来也不记得是冲动,还是经过冷静的思考后得到的结论,试着和老家的一些IT从业者去接触一下,试着和杭州这边接触不是很多的老乡接触一下。不接触不知道,初步接触之后才发现,原来我之前的一些印象和实际情况还是有些差别,渐渐的也对一些事情看淡了,并拿出了魄力试错部分事情。

现在想一想,其实现在的生活也未必有我想的那么不好。多出去走走,提高个人认知水平,应该没太大问题。

温水煮青蛙 ≠ 煎熬

不知道从什么时候开始就逐渐习惯了焦虑馈使型的行为习惯。

我之所以将其称作“焦虑馈使型行为习惯”,是因为每次出现焦虑时,心态很容易出现急躁的情况,且同时会伴随着找各种方法去试图解决或缓解焦虑的持续;但焦虑逐渐减小或阶段性消失时,行为又会回到原先的行为轨迹中。

这样的行为具有很强的特点或特征,大致如下:

1,焦虑成因大部分都来自潜移默化的东西,形成过程时间较长。

2,有些焦虑实际上是患得患失引起。但又不甘心做出牺牲,认为牺牲最小的方案还可以努力努力(牺牲最小的方案有时候很难达成)。

3,焦虑再焦虑,本来是一个很细微的焦虑,但由于转牛角尖,或者在考虑问题时,对部分问题点(矛盾点)过于在意,导致新的焦虑出现,最终形成了滚雪球效应。

4,对现状不满。性格和心态不容易让人安于现状,喜欢登山式前进;但对风险又过于焦虑和回避,容易陷入自我矛盾。

反观,看各种类型不同的人。这种焦虑的习惯性形成,大致根本原因两个:性格和环境

由于性格有优柔寡断和过于激进的特点,因此在做事情的时候,容易多虑,也容易过于激进;两种相反具有冲突性的性格特征混合在一起,若是不能找到一个合理的平衡点,很容易出现眼前的情况。

环境,由于所处的环境一直都处于温水煮青蛙的情况。再和他人做比较的时候,容易出现心理落差。心理落差容易带来某种程度的心理失衡,但这种失衡又是对整个事情的认知不足带来的,即,见的世面很少,无法区分真正意义的好与坏(优与劣)。

同时对自身要求“过分的高”(对自身的要求容易超出自身能力或实际情况太多)。

有时候温水煮青蛙未必是坏事,或许给了思考和缓和的余地。利用现有的资源,好好对自身做一个较为全面或完整的反思,对以后有着很好的帮助。但如果把温水煮青蛙随意等用于煎熬,那么反而浪费自己拥有别人不未必拥有的:“平静和时间”。

切勿心浮气躁,还是要继续加强自身心理控制和调节的建设。

如果回去就要接受羊中无狼

进入社会这么几年下来,我发现越是信息沟通渠道不畅,或沟通减少的情况较为严重时,人普遍的认知问题就更严重。

体现在对自我的认知和对外界的认知上,简单的说容易形成片面理解和过度看高自己。因为有回老家的想法,所以稍微留意了老家那边的IT群,有极少几个群给我感觉非常闭塞,甚至加个群都要搞个神奇的问题验证。即便如此,似乎加群可能还有着一些条件,被拒了几次之后就此作罢,不加了。

同时我也在留意或参与到已加群的一些聊天中,普遍给人感受技术氛围相对弱很多,大家更多关注的是一些装备或设备上的事情。当然也偶尔有几个较为确实厉害的人会说几句正经事情,与此相对的也是有几个典型的会出来不懂装懂的胡乱说一通。

不记得啥时候听到过这么一个说法,羊群中放一头狼,虽然会有羊群被吃完的风险,但养出来的羊个个都比普通散养方式的能跑。

竞争机制要合理引入,但绝非是打着引入竞争而故意制造不平等。老家的IT环境,我看到了相比离家时的成长,但也看到了各种不平等依然的存在,本位主义思想的盛行。以及心胸狭隘的普遍。

先入为主的行为习惯普遍,或多或少也和一个人的见识有着很大的关联。见的多了就更为理解可能性的含义。

面临着有回老家的打算,就必须要接受老家的那种闭塞习俗,也要做好心理落差的准备。事事难料!

好久没有写反思文,即“没有时间”写,也不知道该如何写起。随着年纪增长,想法越来越复杂,而很多心中的矛盾往往也都是由眼前的一些现实问题所致。

何为家?小时候觉得有父母的地方就是家。

长大后,闹独立了;认为自己能够赚钱养活自己,随便租个地方住着就是家。

工作些许年后,觉得拥有自己的房产才是家。再隔几年,觉得步入婚姻才是家。

就眼前来说,我还没步入婚姻,但家在我心中的概念似乎又发生了变化:除了步入婚姻,还有父母才是家。

找对象过程中的各种挫败,以及在外打拼的这几年里对冷漠人性的失望,以及物质为上,功利为主的社会情况;不免让我我时常在反思:“我是不是该改变一下自己了?”久而久之慢慢的也对“外面的世界”产生的一种反感和厌恶之情。

今年是自离开老家后第13个年头的第13次回家过年,回到那个曾经令我反感又厌烦的家。回来以后看到的是长辈们矛盾的淡化,也渐渐的发现父辈们老了,偶然间发现老家生活节奏的舒适和浓郁的人情味。只要是未经世俗过分熏陶的人,你总能在他的身上感受到一种自然的纯朴。

小时候,我就不喜欢刻板和过于复杂迂回的事情;早在几年前,我其实就已经厌倦了复杂的派系人际关系。我向往自由自在,想工作就工作,想出去游玩就游玩的生活。回到老家,老家适宜的生活,让我猛然和自己的向往的人生目标联想到一起,顿时看到了希望一样,因此也就有了“回老家”的想法。

随着年假结束的来临,心态也越来越复杂。

若是回老家,我不得不在老家找个工作维持生计,但老家的就业机会失衡的令人感到可怕。若不回老家,我的心依然在飘。尽管现实如此,但事实上在“是否回老家”问题上犹豫不决的真实原因并非完全如此。

我怕我放下现在所有的积累,回到老家时,我突然“腻”了怎么办?我害怕到时候没有了“后路”,没有了第二个选择。我也不想一辈子碌碌无为或无所事事。

我怕我如果坚持将现在的路走下去看不到结果怎么办?如果在这样继续下去,接下来会发生什么?我到时候是否会后悔当初坚持走下去?

“回不去的家”,我想这句话表达的并非物理含义上的家,而是“心的归宿”。心态上的不稳定,以及面对很多现实问题时,大家处理起来越缺乏人情味的做法,物质至上目标令人极其反感,有时候做选择真的很难,任何选择都有牺牲,而且牺牲都还不小。虽然跟着心做选择是大多数文学著作或过来人的经验,但有时候人的内心又极其容易受蒙蔽。

家,很难!

【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了。

【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 崩溃的正确解决方法

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

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

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

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

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

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