0%

avformat_find_stream_info() 函数的作用

先来看一下 avformat_find_stream_info() 的头文件里的注释对该函数的介绍,本文我们基于 FFmpeg n4.2 版本的源码分析。

1
2
3
4
5
6
7
8
9
10
/**
* Read packets of a media file to get stream information. This
* is useful for file formats with no headers such as MPEG. This
* function also computes the real framerate in case of MPEG-2 repeat
* frame mode.
* The logical file position is not changed by this function;
* examined packets may be buffered for later processing.
* ...
*/
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

注释里说这个方法通过读取媒体文件中若干个 packet 来获取流信息,对于 MPEG 这种没有 header 的文件格式比较有用,也可以计算像 MPEG-2 这种支持 repeat mode 的真实帧率。(MPEG-2 支持对于大量静止的画面设置 repeat mode,重复的帧不用编码和存储,可以减少体积)

Read more »

作为程序员,和命令行打交道很频繁,设置一个赏心悦目的命行行 prompt 或者 Vim 的 status line 主题就很有必要了,不过一般这些漂亮的主题都会用到一些 icon 字符,这些 icon 字符一般的字体里是没有的,今天我们就来聊聊一些带有 icon 字符的字体。

为了有个直观的认识,我们来看一下设置命令行 prompt 特殊主题前后的对比:
prompt_theme

Read more »

一、什么是 atime、ctime、mtime?

Linux/Unix 系统会为每个文件保存一些时间戳信息,我们可以根据这些时间戳来判断文件什么时候被读取过,什么时候被修改过内容,以及什么时候被修改过文件的权限。以下是 atime,ctime,mtime 三个时间戳的介绍。

  1. atime (last Access time)

    最近一次访问文件的时间,访问指的是 读取或者执行文件/文件夹的时间

  2. ctime (last Change time)

    最近一次 metadata 修改的时间,这里修改有两层意思:

    1. 修改文件/文件夹的 metadata,比如 user/group 或者访问权限(比如 chmod)
    2. 修改文件内容
  3. mtime (last Modify time)

    最近一次修改的时间,这里的修改 专指文件的内容修改

注意:

  1. 当创建文件时候,atime、ctime、mtime 都会修改为当前创建的时间
  2. 当修改文件内容的时候,ctime、mtime 都会更新为修改时间
Read more »

这两年来,WebRTC 越来越多地出现在人们的视野,在在线教育,在线医疗等领域的应用也越来越多。大家研究 WebRTC 的热情也越来越高涨,不过 WebRTC 的入门门槛个人觉得稍微有些高,特别是各种概念,比如 NAT 穿越,ICE,STUN,TURN,Signaling server等等,刚开始可能会觉得比较繁杂,不易理解。然后建立连接的整个过程,异步调用比较多,很容易搞混。那么这篇文章里我们会根据 WebRTC 的官方 demo AppRTC 的 iOS 版本来分析一下 WebRTC 从进入房间到建立音视频连接的过程,为了便于了解,我们本次的讨论不涉及到底层的具体实现。

1. 相关概念

我们首先来简单地了解几个概念:

1.1 NAT 穿越(NAT Traversal)

因为 WebRTC 是 P2P 的,很多时候 peer 是隐藏在 NAT 之后的,没有外网的 IP 地址,如果两个 peer 都在 NAT 后面,都没有外网的 IP (或者说都不知道自己的外网 IP),是无法建立连接的。那么 NAT 穿越就是用来解决这个问题的,NAT 穿越也俗称 “P2P 打洞”。常见的两种穿越方式是 STUN 和 TURN。

Read more »

TURN server 可以解决点对点通信里的 NAT 穿透,并提供中继(relay) 的服务。coturn 是一个开源的 TURN 和 STUN 服务器,是基于 rfc5766-turn-server 进化过来的,目前比较成熟。之所以安装 coturn 是借助它提供的 TURN 服务,解决 WebRTC P2P 通信中 STUN 服务器解决不了的复杂内网的问题。比如我尝试过移动4G 和 联通 WIFI 有时候无法通过 STUN 服务穿越内网连接,通过 TURN 服务的中继就可以解决这个问题。下面我们就来介绍一下 coturn 的安装,配置以及测试的过程。

Install coturn

coturn 安装可以参考官方的(安装文档)[https://github.com/coturn/coturn/blob/master/INSTALL],按该文档安装即可。如果是 Ubuntu 系列,可以直接通过 apt 安装,安装完成后会放在 /usr/bin/turnserver

1
apt install coturn

网络配置

以阿里云服务器为例,配置网络安全组/防火墙,开放 3478 的 UDP/TCP 端口,这个我们我们会作为 TURN/STUN 服务器的监听端口,并开放40000~60000的 UDP 端口,STUN 和 TURN 可能会使用随机的 UDP 端口。

Read more »

这篇 blog 来自我们内部的分享,内容比较精简,需要更多的细节信息,请参考 WWDC 2016 - 401 的视频

相信每一个开发者在初学 iOS 的时候,都有过被 Code Signing 坑过的经历,特别是当旁边没有人指导的时候,这也是当时我个人学习 iOS 的时候最困扰的地方,证书,provisioning profile, code signing 等等这些和实际的开发无关的概念,现在还记得苦苦看文档的经历。

Image1 icon
iOS证书申请和签名打包流程图,图来自这里

Read more »

我们知道 Swift 语言支持函数式编程范式,所以函数式编程的一些概念近来比较火。有一些相对于OOP来说不太一样的概念,比如 Applicative, Functor 以及今天的主题 Monad. 如果单纯的从字面上来看,很神秘,完全不知道其含义。中文翻译叫做单子,但是翻译过来之后对于这个词的理解并没有起到任何帮助。

我的理解很简单,Functor是实现了map函数的容器,Monad 就是实现了 flatMap 方法的容器,比如在Swift里,Optional, CollectionType 等等都可以称为 Monad。

既然有了 map, flatMap 又有什么作用呢?两者有什么联系和区别呢?

map vs flatMap

map 和 flatMap 的共同点都是接受一个 transform 函数,把一个容器转换为另外一个容器。

下面主要从维度这一块来解释两者的区别,我们先来简单的定义一下维度

对于类型T,如果类型S是一个容器,且元素的类型包含T,那我们就说:
S(维度) = T(维度) + 1

举个🌰, [Int] (维度) = Int (维度) +1, Int? (维度) = Int(维度) + 1.

Read more »

花了几个小时把 Blog 平台引擎从 Jekyll迁移到了 Hexo 上,换成 Hexo 的主要原因是 Jekyll 用起来总是出问题,比如提交到 GitHub 上生成的静态页速度很慢,以及一些莫名其妙的错误,和对 MarkDown 支持的比较差等等。

找了一圈综合对比,最终发现 Hexo 能完全满足我的需求,功能强大,插件和主题比较丰富,支持多种平台一键部署,比如 GitHub Pages, Heroku, AS3, 甚至直接rsync, 有了之前的教训,我果断选择了通过 rsync 放在了自己闲置的一台Digital Ocean的VPS上。更吸引我的是Hexo是基于 NodeJS的,我对 Node 和 EJS模版引擎比较熟悉,有无法满足的需求时,就直接顺手添加上了,比如这次分页的方式,对友言的评论的支持,以及UI上的一些改动等等。

Read more »

今天科比正式退役,在未来的日子里,也许还会有像科比一样有天赋又努力的球员出现,但我们却不再有青春去追随了。
—沃茨•其索特

1 什么是协变与逆变

刚开始看到协变(Covariance)和逆变(Contravariance)的时候,差点晕菜,反复查了一些资料,才稍有些自己的体会,难免有理解不对的地方,欢迎指出 :]

在计算机科学和类型的领域内来看,变化(variance)这个词指的是两个类型之间的关系是如何影响从它们衍生出的两种复杂类型之间的关系的。相对于原始类型,这两种复杂类型之间的关系只能是不变(invariance),协变(covariance)和逆变(contravariance)之中的某一种。

这段比较拗口,我们一步一步拆解,既然上面提到了两个类型之间的关系,在主流的编程观念里,类型之间的关系中通常会包含子类型(subtype) 和 父类型(supertype)。

首先假设 Cat 是 Animal 的子类,就是说 Cat 是 Animal 的 subtype,可以看作上面的“原始类型”,然后有两个衍生出来的 List<Cat>List<Animal>类型,就是从 Cat 和 Animal 衍生出来的两种复杂类型。

那么我们就可以这么来解释协变和逆变了:

  • 协变: 如果说 List<Cat> 也是 List<Animal>的subtype,也就是衍生类型的关系和原来类型( Cat 与 Animal)的关系是一致的,那我们就说 List 是和它的原来类型协变(共同变化)的。
  • 逆变:如果说List<Cat>List<Animal>supertype,也就是衍生类型的关系和原来类型( Cat 与 Animal)的关系是相反的,那我们就说 List 是和它的原来类型逆变(反变)的。
  • 不变:如果说List<Cat> 既不是 List<Animal>的subtype,也不是supertype,也就是说没有关系,则说是不变的。
Read more »

介绍

FLEXLoader 是一个我在上周末写的一个可以动态加载FLEX的开源越狱插件,它以加载动态库的方式注入到系统App和用户的App中(欢迎使用star, fork, clone等一切方法蹂躏我~~)。FLEX全称是”Flipboard Explorer”,是Flipboard团队开发一组调试和探测App的开源工具,功能非常强大,比如查看和修改View的层级结构,查看和修改堆内存中的对象信息等等,更多FLEX介绍和使用信息参考这里

FLEXLoader参考了RevealLoader,顾名思义,它是一个加载Reveal动态库的越狱插件,是一款非常方便的插件,如果你经常用Reveal来查看和调试,一定不要错过。我把它的源码做了一些修改,把Reveal的动态库改成了FLEX的动态库,因为FLEX官方只提供了源代码,所以我参考了Tony的这篇文章编译了一个动态库,如有有兴趣,也可以直接用我已经构建好的Xcode工程FLEXDynamicLibProject来编译。

安装FLEXLoader

有下面两种安装方式:

  1. 在Cydia中搜索Flipboard FLEX loader并安装(BigBoss源)
  2. 如果安装有越狱的开发环境,比如theos,可以自己来编译安装,配好环境变量后,make package install一下(也可以自己编译FLEX的动态库替换掉工程中的FLEXDylib.dylib).
Read more »