流光飞舞

2015 年 2 月 27 日

词曲:黄沾

迎浮生千重变
跟有情人 做快乐事
别问是劫是缘

这,谁做得到??

WordPress去掉google font的引用

2015 年 2 月 26 日

目前所有插件都不靠谱,手动来吧。

我的主题没有用到google font,如果主题使用了google font还要记得把主题里的引用也要去掉。

不信抬头看,苍天饶过谁 —— 《狼图腾》观后感

2015 年 2 月 25 日

  旧时代在慢慢死去,新时代里没有自己的位置。
  曾经无敌的技能慢慢变得一文不值不说,还拦别人前进的道。
  
  你们说,在这样的大环境下。作为一个个体,能怎么办呢?
  
  站在这个时刻的我们,怎样做才是最好?
  挣扎?反抗?屈服?接受?忍耐?
  
  陈阵作为一个有退路没顾忌的家伙,他当然可以养小狼。
  当然他可以抱住所爱,享受那轻轻一吻。
  
  甚至他可以在多年后写一本讲述这段故事的书。
  坐收版税的同时,收获人们的钦佩和道德的认可。
  来自新时代的人儿,无法他做什么,都透着那么轻松写意。
  
  可是心中真有“图腾”的毕利格老人怎么办?他无法突破自己去囚困心中的神。
  可是另外倾慕噶斯迈的藏族小伙子怎么办?他无法允许自己觊觎人别的妻子。
  
  甚至,那美丽而可怜的女人怎么办?那个带着孩子的活在现实里的女人,她怎么办?
  
  对于他们而言。
  心中那些曾经让自己强大的信念,一瞬间全变成绳索。
  依然还是那样强大,捆得自己动弹不得。
  想尝试挣扎一下,立马勒出血印子。
  
  怎么办?
  
  影片安排老人慢慢死去,年轻人光荣战死。
  虽然勾得我眼泪直流,但这大概已经是比较好的结局了。
  
  不然呢?拿枪上山,续集来一部《智取威虎山》?
  
  在文明更迭的最后,别说利益形势,就连道德标准也无法自善其身的。
  不及时战死,就要变成被镇压,被剿灭,被大快人心。连眼泪都骗不到了。
  
  怎么办?
  
  我真想不出答案。
  
  
  只是。
  那新时代来的人儿啊,地方是你的,神是你的,女人。。。你也拿走吧。
  但求你有没有可能慢一会儿,温柔一点,学习一点点技巧。
  没有前戏真的会痛。
  
  你是不是知道,天道好轮回。
  

时光是把杀猪刀,但爱直接割喉 —— 《消失的爱人》观后感

  代入感好强的片子,让我窒息。
  缓过来之后,有个疑问。
  
  Amy为什么不和富翁Neil在一起,最后隐身希腊。
  非要迈出最关键那一步,把自己陷入最后那样无可自拔的结局呢?
  如此坚决的她,到底在追求什么?
  
  她和Nick之间确实有经济问题,但Neil一起不就没这方面问题了么。
  为了她反复提及的安全感?这问题Neil一样可以解决,去希腊开始新的生活啊。
  控制欲?Neil被她操纵了那么多年还不够满足?
  被爱被重视的感觉?Neil给的还不够?
  
  Neil一口气给了她那么多那么多,他说:“只要你要,只要我有。”
  她居然用那么干脆残忍的一刀回答:“这些都不是我想要的!”
  
  说得那么大声。
  
  这个女人到底在追寻什么呢?
  如果此片是在隐喻婚姻的意义,那我们在婚姻关系中追寻的是什么呢?
  
  我想了好久。
  
  ……
  
  “归属感”?
  
  所谓归属感,就是这两个问题的明确答案:
  我属于谁?
  谁属于我?
  
  Neil属于Amy,但Amy不认为自己属于他。
  Amy也许觉得自己属于Nick,但她又感觉不到Nick属于她。
  
  如果女主是在追求这个玩意,那她必将获得苦痛的一生。
  她能力越强,越有力的挣扎,就会给自己越深重的伤痕。
  
  现代社会中,我们把自己的每一面都拿出来交换我们所需。
  把专业献给老板,换取工资。
  把激情献给女人,换取满足。
  
  但是若要说某一个具体的人,而不是他身上的某一个角色或者社会属性,一个完全的人。
  她完全地属于我。
  或者我完全属于她。
  
  这种可能性有没有呢?
  
  我觉得答案不乐观。
  
  电影《成为简·奥斯汀》中奥斯汀为什么和勒弗罗伊分手?他们都已经在私奔的路上了啊。
  因为奥斯汀发现勒弗罗伊有一大笔她不知道的债务。
  所以即使是私奔这么极端的行为,也不能说明她爱上的,不是她爱人的某一个或几个面。
  不能说明是一个“完全的人”爱上了另一个“完全的人”。
  
  一般意义下,私奔即意味着彼此是生命的最重要,重到大于其它一切的总和。
  但即是这样的关系,和相互归属的关系依然相去有日。
  勒弗罗伊的债务意味她要放弃“自由写作”的那部分自己。
  
  “我做不到,我又不属于你。”
  对吧?
  
  可谁能让自己完全地属于另一个人呢?
  如果没人可以做到,那谁又能得到一个这样的人呢?
  
  对于追寻不存在的东西的下场结局,庄子比开箱刀还利——
  
  “殆已。”
  

DarwinStreamingServer搭建RTSP服务器

2015 年 2 月 10 日

安装

修改配置

重启

Mac下为Android Studio编译Ffmpeg(二)Android Studio部分

2015 年 1 月 27 日

Android Studio和Eclipse不太一样,它有一定的自动生成Android.mk并自动搞定JNI的能力。
但目前还并不足以让我们使用起来Ffmpeg库。
因此我们的思路是禁用掉Android Studio自动ndk-build的功能,手动编译我们的C代码达到目的。

首先当然要新建一个Android Studio项目。
我们使用$ROOT_DIR指代项目根目录。

1、Android Studio配置ndk路径

$ROOT_DIR/local.properties原先只配置了sdk。

给它增加一行ndk的配置

2、配置build.gradle

项目里面有两个build.gradle,一个在根目录下,一个在$ROOT_DIR/app/src下,我们要修改的是后者。
A>添加这一段以禁用自动ndk-build。

B>添加这一段让它知道用库

修改后的build.gradle是这样的。

3、生成头文件

执行命令,注意路径要根据自己的情况更改。

会生成这个文件$ROOT_DIR/app/src/main/jni/com_example_chengang_myapplication_MainActivity.h

4、编写C文件

$ROOT_DIR/app/src/main/jni/ovsplayer.c内容如下:

5、编写Java文件

$ROOT_DIR/app/src/main/java/com/example/chengang/myapplication/MainActivity.java内容如下。
其中getStringFromNative()方法是我们实现的,打印了Ffmpeg库的版本号(我编译的这个是3673444)和视频文件的信息出来。

附上布局文件是这样的。

6、编写项目Android.mk

Android.mk放到$ROOT_DIR/app/build/intermediates/ndk/debug/下。
注意其中的绝对路径”/Users/chengang/Code/Android/MyApplication4″是咱们的$ROOT_DIR。

简单说下LOCAL_LDLIBS和LOCAL_SHARED_LIBRARIES的区别,前者链接系统库,后者链接第三方库。
并不能换着用。

7、编译C代码

在终端下执行这个命令编译C代码。

8、运行项目

回到Android Studio中Ctrl+R运行项目。
会看到手机上打印出Ffmpeg库的版本号(我编译的这个是3673444)和视频文件的信息出来。
Ffmpeg库已经可以调用了,然后继续写自己的逻辑就好了。

9、另外

另外说两个C代码中可能遇见的错误:
A>如果你通过标准库想得到文件大小,又写错了文件名。安卓上,在不存在的文件的句柄上执行fseek会报如下错误:”could not disable core file generation.”;
B>如果avformat_open_input()返回-1330794744了。那有两种可能,一是你忘记调用av_register_all()了,二是编译Ffmpeg的时候没有编译进对应的DEMUXER或者指定了disable-everything。

本文前半配置ndk的部分见这个链接:Mac下为Android Studio编译Ffmpeg(一)ndk部分

Tags

Mac下为Android Studio编译Ffmpeg(一)ndk部分

本文参考http://www.roman10.net/how-to-build-ffmpeg-with-ndk-r9/。
但它只适合做编码,而且没有Android Studio配置的部分。

1、下载ndk

我下的是r10d版本。

2、解压ndk

不要解压,文件权限会出错。执行之,会自动解压,然后mv到想放的地方。我放到了”/usr/local/bin/android-ndk-r10d”(此目录之后用$NDK_DIR指代)。

3、下载Ffmpeg

我下的是2.5.3版本。

4、解压Ffmpeg

解压Ffmpeg到$NDK_DIR/sources/ffmpeg-2.5.3。

5、修改Ffmpeg编译配置

在ffmpeg-2.5.3目录下把configure文件中的这几行,目的是去掉默认生成的库名字libavcodec.so.55最后那个”55″的版本号。

6、编译Ffmpeg

在ffmpeg-2.5.3目录下创建文件build_android.sh。
注意前三行要按照自己的路径正确配置。

保存后执行

编译会花上一段时间。

7、查看编译结果

编译完成后$NDK_DIR/sources/ffmpeg-2.5.3下面会多出一个android目录,里面就是我们想要的编译好的库。

其中libavcodec.so、libavfilter.so、libavformat.so、libavutil.so、libswresample.so、libswscale.so都是软链,没有用,可以删掉。

8、给Ffmpeg库写Android.mk使其可用

创建$NDK_DIR/sources/ffmpeg-2.5.3/android/arm/Android.mk文件,内容如下:
要注意其中.so前面的数字应该改成你的ffmpeg版本编译出来的数字。

至此ndk配置完毕,后面是配置Android Studio的部分。
见这个链接:Mac下为Android Studio编译Ffmpeg(二)Android Studio部分

Tags

Rust官方指南摘抄(八)并发任务

2015 年 1 月 6 日

Rust官方指南摘抄系列内容如下:
(一)语法基础
(二)猜数游戏
(三)模块、测试和宏
(四)指针
(五)模式匹配
(六)方法语法、泛型和抽象方法
(七)闭包和迭代器
(八)并发任务

并发原语

1、Rust使用“任务”来描述并发。任务是轻量级的原语,抛弃了不安全的内存共享模式,使用消息传递作为交流手段。

2、任务是作为一个库被实现的,并不是语言的一部分。所以今后可能会出现更多的并发库去适应各种并发环境。

3、任务使用spawn()方法来表达。

4、spawn接收一个proc,凡是proc用过的变量,往后都不能使用了。
这是为了并发安全而考虑的,虽然其他很多语言允许这种用,但是Rust决定禁止这种方法,并选择在编译器直接报错。

消息传递

5、如果任务想和外面通信,可以使用频道(channel)。
很像linux里的pipe是不。

注意.recv()方法是阻塞的,它的非阻塞版本是.try_recv()。

6、和pipe一样,如果需要双向通信。
那就需要两个频道。

7、Sender都是Receiver泛型定义的,所以频道可以传输各种数据类型。
但只能是一种数据类型,如果往一个频道里先传了int,后续又传string是不行的。

Future

1、从基本的原语可以衍生出很多并发模型,Rust的标准库中也有一些。

2、比如说频道之外的另一种沟通方式Future。

错误处理

1、fail!宏可以帮助我们传递失败消息。

2、失败的任务不可恢复。但是它可以提醒其它任务它失败了。
task::try会帮助我们。

Tags

Rust官方指南摘抄(七)闭包和迭代器

Rust官方指南摘抄系列内容如下:
(一)语法基础
(二)猜数游戏
(三)模块、测试和宏
(四)指针
(五)模式匹配
(六)方法语法、泛型和抽象方法
(七)闭包和迭代器
(八)并发任务

闭包

1、Rust中的匿名函数被称为闭包。

2、闭包可以读取它被定义的那个作用域内的变量,比如下面这个不接受参数的闭包。

3、闭包借走了它从环境中读取的变量,在它归还之间,要遵守Rust的拥有者原则。

4、闭包特性可以帮助我们获取函数式编程两大优点之一高阶函数(另一个是惰性计算),造出“返回函数的函数”。

过程

1、Rust中的闭包还有一种形式被称为过程,使用proc关键字来定义。

2、过程是为并发而设计的,我们会在并发的章节继续谈到它。目前我们只需要知道,同一个过程不可以被调用两次。

迭代器

1、rang函数的返回,就是一个迭代器。所谓迭代器,都可以调用.next()方法。

其实等价于显式的.next()调用如下:

2、rang()在Rust中是反模式的。下面这种写法并不被提倡。

下面这样写更好一些。代码更清晰,而且执行效率更高。
因为我们不再依赖vec的索引,.iter()帮助我们避免了不必要的边界检查。

3、值得注意的是,迭代器给我们的是数据的引用而不是数据的拷贝。
它临时借来了数据,避免了数据拷贝的开销。
当然,无论把哪个交给println!(),它都会帮我们搞定它。

消费者

1、进一步阐明为什么range()是反模式的,我们需要明确三个概念。
a> 迭代器:返回一组数据;(range()就是这类)
b> 迭代适配器:作用在迭代器之上,返回一个数据被处理过的新的迭代器;
c> 消费者:作用在迭代器之上,返回最终数据。

2、消费者之一 collect(),最常用的消费者,把迭代器里的数据弄成一组返回回来。
需要指明数据类型。

3、消费者之二 find(),找出符合条件的值。它可以接受一个闭包。

4、消费者之三 fold()。带状态存储的迭代器消费者。

就这段代码而言。
每一轮的计算结果会存放在sum里面。最终total变量的值等于 fold中第一个参数0与迭代器中所有值的合。

5、借助迭代器和消费者,我们可以实现函数式编程的另一个重要优点“惰性计算”。
值只在真正被下一个流程需要的时候才真正被生成和计算。
这使得我们直接申请一个1到无穷大的数组而完全不用考虑内存和CPU资源的问题。

6、按照上面说的,再来一个高级迭代器。

迭代适配器

1、迭代适配器之一 filter()。

2、迭代适配器之二 map()。

但这会得到warning

因为是惰性的,迭代器要求后续操作一定要明确把值取走。

3、迭代适配器之三 take()。下例明确取5个。

4、我们可以让迭代器打头、迭代适配器放在中间,消费者放在最后结合起来用。就像下面这个例子。

Tags

Rust官方指南摘抄(六)方法语法、泛型和抽象方法

2015 年 1 月 5 日

Rust官方指南摘抄系列内容如下:
(一)语法基础
(二)猜数游戏
(三)模块、测试和宏
(四)指针
(五)模式匹配
(六)方法语法、泛型和抽象方法
(七)闭包和迭代器
(八)并发任务

方法语法

1、一般我们方法嵌套方式是这样的:

但如果我们想弄成这样:

impl关键字可以帮忙。

2、也可以不用&self,在new的时候就开始搞。

这种写法在Rust代码里面很常见。

范型

1、感觉有点像C++的模版,范型也叫参数多态(parametric polymorphism)。它让我们可以把指定具体类型的工作推迟到实际实例化时去做。

2、我们来试一下用T表示范型,比如说这样。

3、范型可以帮忙我们在多个数据类型共用同一套方法的时候大幅减少代码量。

4、虽然习惯上用T指代type,用E指代error。但它们其实可以是任何一个大写字母。

5、在返回结果时尤其好用。

如果顺利,我们可以返回计算结果。
如果有问题,我们返回字符串来描述失败原因。

6、实战一小下。

7、显然范型需要配套泛型函数。它“可能”长这个样子。

但编译时会报错

因为编译器不知道范型T是否可以做”==”的操作,所以报错了。,
想解决这个问题,就需要用到Rust中Traits的概念了。
往下看。

抽象方法

1、用trait关键字声明目前的类是否拥有某个方法。类似C语言的.h文件。

2、一旦引入了trait的概念。就可以检查某种数据类型是否拥有某个方法。

3、一个比较完整的例子。这样我们就可以使用泛型,但依然在编译期检查出那些非法的输入类型。

如果我们输入

会得到错误

4、我们可以给任何东西增加抽象方法,甚至是基本类型int。

5、为了防止上面那种事情影响到别人呢,Rust规定trait必须把自己框在一个范围内。

6、最后,按照惯例,Rust要表扬一下自己。
Rust是用单态(monomorphization)实现这一堆特性的。
比如我们写这样的代码。

它会在编译期就被展开成类似如下的代码:

在运行期一切都已经静态化了,并不会在运行期去猜测使用哪个方法。所以不会在运行期引入额外的开销。
但因为把方法拷贝了多份,编译出来的文件会稍大一些。

Tags