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

admin

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

大小端安全简单访问技巧


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总结

迁移站点完成已关闭评论

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

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

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

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

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

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

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

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

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

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

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

2019-03-29 | | [心理学], [我的认知系列], [窥视自我], *生活*, 思考

认知成长=目标达成/失败=想法+行动已关闭评论

温水煮青蛙 ≠ 煎熬

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

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

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

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

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

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

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

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

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

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

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

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

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

2019-03-21 | | [我的认知系列], [窥视自我], *生活*, 思考

温水煮青蛙 ≠ 煎熬已关闭评论

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

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

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

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

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

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

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

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

2019-03-14 | | [我的认知系列], *生活*, 思考

如果回去就要接受羊中无狼已关闭评论

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

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

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

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

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

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

今年是自离开老家后第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了。

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循环的差别已关闭评论

【h264、baseline、flv】使用baseline做双向强交互直播不利的几点因素

再说baseline做强交互不利因素之前,先说说现在直播的场景情况。

 

场景如上图,推流段不是移动平台,就是PC机。当然最近几年也出现专门用来推流的定制盒子,本质不是一个嵌入式windows,就是一个android设备(android设备较多)。

  • 而对于PC机作为推流端来说其实问题并不大,只要在保证带宽足够理想的情况下,采用264的任何一种profile都能尽可能的做到最大延时接近编码器固有延时的效果。同样对于使用何种容器来说问题都不大。

 

  • 但对于移动设备来说,需要匹配的情景就很多了,主要是由于移动设备的电池续航能力、操作系统小类别太多、整体性能表现。在使用264编解码时,一般尽量采用硬编解码,对于实在没有办法的情况下才使用软编解码。就仅仅一个硬编解码上就存在诸多差异,例如有些profile硬件不支持,或者rom上存在一些问题导致本该支持的profile,支持的不好或者根本不支持。

 

  • 除了上述提到的问题以外,其实还有一个隐形问题,那就是用户使用习惯问题。现在的用户越来越偏向于使用web方式展现的产品,一方面对于开发者来说,界面改动较为简单灵活,另一方面对于用户来说,只需要打开浏览器即可,简化使用步骤。

然而上述提到的这些问题,就造就了可能大家会想到flash、h5和native应用,对于native应用来说还好,开发起来虽然周期长,但可塑性比较强。对于flash和h5来说可选择余地就非常小了。

暂时不说flash和h5本身在做双向强交互直播是否可行,先说一说两者采用的协议类型。对于flash来说:

  • 通讯协议为rtmp系列协议(包括rtmpt等),协议本身并不是太复杂,但涉及当初并不是用来做双向强交互的直播协议,因此协议本身就没有在双向强交互上做太多的考虑。

 

  • 由于协议本身所承载的流媒体容器格式为flv或f4v,现在大部分直播平台基本采用的是flv作为容器,同时flv也是一种较为简单易用的容器

 

  • 但由于flv容器格式的限制,在adobe官方手册中就已经说明,flv容器支持的264的profile范围中,目前仅对baseline、extended、main、high、high10、high4:2:2、high4:4:4,在经过简单测试之后,如果不考虑flash端推流的情况下,用户电脑(移动端一般用h5,不用flash)性能具备一定保证的情况下,再根据官方手册并测试(as3手册),没有实际去测试过high10,不过脑补得知high10也是可以的,但延时太大,也有可能会引起其他flash异常。因此往往最佳的选择就在baseline、main、high中选择,因为他们的颜色编码是8bit的。从解码效率和广泛性来说,这三种都可以。

 

  • 但由于是双向直播,因此,在这时就需要考虑编解码器的时延问题。这时,大家一贯的做法就是关闭B帧编码,这样即可极大的提高编解码延时。当关闭了B帧编码之后,剩下几种profile互相比拼的就是在给定的一个平均分辨率、gop的情况下,编解码固有时延和数据码率,以及支持的广泛性。实测之后发现high其实在不同浏览器的flash上表现存在一定差异,主要情形为编解码速度、性能开销等等。因此在flash上使用high这种方式时,还需要综合考虑。

 

接下来说一说h5方式的直播:

  • h5方式的直播一般是通过websocket进行通讯,协议是hls,容器格式为ts、ps。然而我对hls和ts、ps都不是很了解。

 

  • h5支持还有待进一步推广,目前在较新的chrome系浏览器和较新的firefox浏览器上均支持较好。IE系暂时较弱(我把edge理解成IE系)。

 

  • 就目前来说,从开发手机端开发难度,和各手机厂商的支持力度上,无论是webview app还是native app来说,hls+ps/ts也是较优选择。

 

  • 通过看了苹果官方的FAQ得知,hls协议似乎仅仅支持baseline、main、high三种,不清楚是由于ts、ps容器特性导致的,还是hls协议特点。因此在决定使用哪一种profile时,又回到了和flash一样的情况下。

 

通过以上可以得知,实际上在使用x264编码时,最终在profile的选择上基本就限制在了baseline、main、high三种。从算法复杂度上来上讲,baseline是最为简单,而high是较为最为复杂(主要是预测模型比前两者多不少)。

不过在实际工程应用中,我们还是做了一个比较脑残又没有办法的决定,那就是使用baseline。原因有二:

  1. 我们使用的编码库是openh264,早期版本的openh264宏块分割方式较小,也仅仅支持baseline,对main也只是仅限于试验阶段。
  2. 在同样的profile级别下,参数大致相同的情况下,openh264的编码时延比x264的utral模式下略高,但码率略低(未做定量测试,简单定性测试得到的结论)。编码完的数据解码出来的视觉感受差别不大,反正都是渣画质。

考虑到使用场景和当时网络的大环境,确实选择openh264,即是无奈的选择,也是一个极其脑残的选择。说无奈主要是现实,说脑残是因为压根就没有做过定性分析。。。。。。

然后接下来就开始“数落数落”baseline不适合做双向强交互直播的原因。在看x264的代码时,偶然对编码中的预测做了少许的了解。

—- 我是装逼的分割线 1号 —-

传统上对一副图像的处理,一般的理论是基于“分割”,由于图像一般情况下具有前景和后景之分,也就是说,前景和背景之间存在着大量的局部图像细节,对于图像压缩中的思路往往是,尽量将相似的区域用差别不大的统一一个区域去表达,对于差异较大的区域,尽量在用较多的数据量去存储以此保留图像的局部细节。

那么就会存在如何分割图像的问题。如果是一副简单单值图,例如大学时代我做的非矢量图压缩(理论基础差不多),那么只需要根据图像分辨率,做相应的最佳分割快大小计算,并做简单切割即可。将区域内的有色的点和无色的点进行记录,并按做纵向或横向切割成色带,记录色带中有色点或者无色点的坐标值即可。整个思路转换成代码思维,类似于多级联映射表。当然这个做法的关键还在于公式如何设计,即如何动态计算切割区域的大小。由于是做印章方面,所以图像不会太大,因此公式也非常简单。

最终压缩可以理解成单值图的无损压缩,实测试之后,和转换成矢量图之后的文件大小相比,应该两者都会比现在主流的大部分图像编码小非常多。

接着通过类似7z、rar工具里面的二进制压缩算法进行再次压缩,文件最大还能缩小60%左右。一个500k的位图最终生成文件在3k左右。

—- 我是装逼的分割线 2号 —-

由于有上面的实践基础,因此在理解264的压缩时,我也能够理解到“分割”时的重要性。

首先,在baseline模式下,x264的预测模型相对于其他high来说,非常简单。这样的情况就决定了,在局部的细节切块相比high来说有着很多不足,对二进制数据进行压缩前就已经输在起跑线了。即细节丢失比high多。

其次在编码算法上(或者说压缩算法上),baseline仅仅使用cavlc,而对其他两者来说他们既可以使用cavlc也可以使用cabac。没有做过定性或者定考量分析,但通过网上资料获知,cavlc的效率似乎没有cabac高,具体在哪些指标有所体现目前暂时并不清楚。

因此,可以得知。baseline除了在实时性上满足了双向强交互直播对时间的要求,对于相同质量下的压缩比并不是很好。但又由于baseline相对其他profile的简单特点,其实广泛性还是比较不错的。

手里有台android 2.3时代的三星手机,对baseline的视频进行解码,手机基本可以应付(不清楚是硬解还是软解,因为当时的arm好像还有没有对264硬解做太多优化),但相同视频长度的main和high的话,那就有点头疼了。看来baseline对老旧手机还是比较“良好”的。

2017-11-22 | | matlab, 数据结构 & 算法, 音视频_图像相关, 音视频编解码

【h264、baseline、flv】使用baseline做双向强交互直播不利的几点因素已关闭评论

【x264、宏块、邻居】x264中对宏块预测方向与邻居类型的定义

在x264中,由于单一宏块预测方向与264规范定义实际上是一直的,即预测方向只有:左(left)、上(top)、左上(left-top)、右上(right-top)。

没有其他的另外四个方向,估计可能是zig-zag的数据排列有关,或只是由于对称关系,不需要做重复预测。

有上述4中预测方向,x264中定义了几种邻居关系(下面拿I帧4×4的宏块距离说明):

  • 垂直方向,即I_PRED_4x4_V、I_PRED_4x4_DC_TOP,实际上是向上方向预测(top)
  • 水平方向,即I_PRED_4x4_H、I_PRED_4x4_HU、I_PRED_4x4_DC_LEFT,实际上是向左方向预测(left)
  • 左边和向上方向,即I_PRED_4x4_DC
  • 向上旋转到右上方向,即I_PRED_4x4_DDL、I_PRED_4x4_VL
  • 左边旋转到向上方向,即I_PRED_4x4_DDR、I_PRED_4x4_VR、I_PRED_4x4_HD
  • 左边旋转到向上方向,即I_PRED_4x4_VL
  • I_PRED_4x4_DC_128代表自身?
2017-11-21 | | 数据结构 & 算法, 音视频_图像相关, 音视频编解码

【x264、宏块、邻居】x264中对宏块预测方向与邻居类型的定义已关闭评论