在mac下安装ffmpeg

通过Homebrew安装

1
brew install ffmpeg

手动安装

  • 下载ffmpeg可执行文件到目录‘Downloads’
  • 执行以下shell命令
1
2
3
4
cd Downloads
sudo mkdir -p /usr/local/bin/
sudo cp ./ffmpeg /usr/local/bin
sudo chmod ugo+x /usr/local/bin/ffmpeg
  • 打开文件.bash_profile

    1
    open -e ~/.bash_profile
  • 在文件末尾加入以下代码设置环境变量

    1
    export PATH="/usr/local/bin:$PATH"
  • 保存文件,重启终端,运行 which ffmpeg, 如果返回 /usr/local/bin/ffmpeg,表明安装成功

Runtime

objc_object

objc_class

isa指针


cache_t

  • 用于快速查找方法执行函数
  • 是可增量扩展哈希表结构
  • 局部性原理的最佳应用

class_data_bits_t

  • class_data_bits_t主要是对class_rw_t的封装
  • class_rw_t代表了类的读写信息、对class_ro_t的封装
  • class_ro_t代表了类的只读信息

class_rw_t

class_ro_t

method_t

Type Encodings

总体结构

对象、类对象、元类对象

  • 类对象存储实例方法列表等信息
  • 元类对象存储类方法列表等信息

消息传递

obj_msgSend(xxx)
obj_msgSendSuper(xxx)

缓存查找

例: 给定SEL, 目标是对应bucket_t中的IMP:
cache_key_t 通过f(key)得到bucket_t

  • 对于已排序列表,采用二分算法查找对应执行函数
  • 对于未排序列表,采用一般遍历查找对应执行函数

**父类逐级查找

消息转发

动态方法解析

@dynamic

  • 动态运行时语言将函数决议推迟到运行时
  • 编译时语言在编译期间进行函数决议

Network

HTTP

Get和Post的区别

安全性

幂等性

可缓存性
请求是否可以缓存(get/head)

连接建立断开流程

HTTP特点

  • 无连接(补偿:Http的持久连接)
  • 无状态 (补偿:Cookie/Session)

Http的持久连接
设置请求头部字段:
connection: keep-alive
time: 20
max: 10 (该连接最多能发送的请求数)

判断一个请求是否结束

  • Content-length: 1024
  • chunked, 最后会有一个空的chunked

Charles抓包原理
中间人攻击

HTTPS连接建立流程

会话秘钥 == Random S + Random C + 预主秘钥

TCP/UDP

UDP
无连接
面向报文

功能:

  • 多端口复用分用
  • 差错检测

TCP
特点:面向连接,可靠传输,面向字节流,流量控制,拥塞控制
面向连接
三次握手(规避两次握手时超时重传可能建立不必要的连接)
四次挥手 (存在半关闭状态)
可靠传输

  • 无差错:发生传输错误时候,会超时重传

  • 确认丢失

  • 不重复

  • 按序列到达

面向字节流

流量控制
滑动窗口协议

拥塞控制
慢启动,拥塞避免,快恢复,快重传

DNS解析

域名到IP地址的映射,DNS请求采用UDP数据报,且明文

查询方式

  • 递归查询
    client -> 本地DNS -> 根域DNS -> 顶级DNS -> 权限DNS

  • 迭代查询

DNS解析常见问题

  • DNS劫持问题
  • DNS解析转发问题
  • 如何解决DNS劫持


如何修改cookie?

  • 新cookie覆盖旧cookie
  • 覆盖规则:name、path、domin等需要和原cookie一致

如何删除cookie?

  • 新cookie覆盖旧cookie
  • 覆盖规则:name、path、domin等需要和原cookie一致
  • 设置cookie的expires=过去的一个时间点,或者maxAge=0

如何保证cookie的安全?

  • 对cookie进行加密处理
  • 只在https携带Cookie
  • 设置Cookie为HttpOnly,防止跨站脚本攻击

Session

Session也是用来记录用户状态,区分用户的;状态存放在服务端
Session和Cookie关系是怎样的?

  • session需要依赖于Cookie机制

Runloop

什么是Runloop

runloop是通过内部维护的事件循环来对事件/消息进行管理的一个对象

  • 没有消息需要处理时候,休眠以避免资源占用 (用户态->内核态)
  • 有消息需要处理时,立刻被唤醒(内核态->用户态)


CFRunloopSource

  • source0(需要手动唤醒线程)
  • source1(具备唤醒线程的能力)

CFRunloopTimer
基于事件的定时器,和NSTimer是toll-free bridged

CFRunloopObserver
观测时间点

  • KCFRunLoopEntry
  • KCFRunLoopBrforeTimers
  • kCFRunLoopBeforsources
  • kCFRunLoopBeforeWaiting(即将产生用户态切换内核态)
  • kCFRunLoopAfterWaiting
  • kCFRunLoopExit

NSRunLoopCommonModes

  • CommmonModes不是实际存在的一种Mode
  • 是同步Source/Timer/Observer到多个Mode中的一种技术方案

RunLoop和NSTimer
void CFRunLoopAddTimer(runloop, timer, commonMode)

RunLoop和多线程

  • 线程和Runloop是一一对应的
  • 手动创建的线程默认没有Runloop

如何实现一个常驻线程
step1: 为当前线程开启一个runloop
step2: 向改runloop添加一个Port/Source等维持Runloop的事件循环
step3: 启动该runloop

多线程

GCD

  • 同步/异步 和串行/并发
  • dispatch_barrier_async
  • dispatch_group

同步/异步和串行/并发

  • dispatch_sync(serial_queue, ^{ task })
  • dispatch_async(serial_queue, ^{ task })
  • dispatch_sync(concurrent_queue, ^{ task })
  • dispatch_async(concurrent_queue, ^{ task })

如何用GCD实现多读单写

dispatch_group使用

NSOperation

需要和NSOperationQueue配合实现多线程方案

  • 添加任务依赖
  • 任务执行状态控制
  • 最大并发量

任务执行状态控制

  • isReady
  • isExcuting
  • isFinished
  • isCancelled

状态控制

  • 如果只重写main方法, 底层控制变更任务执行完成状态,以及任务退出
  • 如果重写了start方法, 自行控制任务状态

iOS当中都有哪些锁

  • @synchronized(一般创建单例对象时候使用)
  • atomic(属性关键子)
  • OSSpinLock (循环等待询问,不释放当前资源, 用于轻量级数据方法, 存在优先级反转问题)
  • NSRecursiveLock
  • NSLock
  • dispatch_semphore_t(create/wait/signal)

内存管理

内存布局结构

iOS内存管理方案(objc-runtime-680)

  • TaggedPointer
  • NONPOINTER_ISA

  • 散列表


ARC

  • ARC是LLVM和Runtime协作的结果
  • ARC中禁止手动调用retain/release/retainCount/delloc
  • ARC中新增weak,strong关键字

引用计数管理




delloc实现:

obj_destructInstance()实现:

clearDeallocating()实现:

自动释放池(AutoReleasePool)

  • 以栈为结点通过双线链表的形式组合而成
  • 与线程一一对应
  • 在当次runloop将要结束的时候调用 AutoReleasePoolPage::Pop
  • 多层嵌套就是多次插入哨兵对象



AutoReleasePoolPage::Pop

  • 根据传入的哨兵对象找到对应位置
  • 给上次Push操作之后添加的对象依次发送release消息
  • 回到next指针到正确位置

循环引用

  • 自循环引用
  • 相互循环引用
  • 多循环引用

如何破除循环引用

  • 避免产生循环引用
  • 在合适时机手动打破循环引用

具体解决方案

  • __weak
  • __block
  • __unsafe_unretained(会产生悬垂指针)

Note:

  • MRC下,__block修饰对象不会增加引用计数,避免了循环引用
  • ARC下,__block修饰对象被强引用,无法避免循环引用,需要手动解环

NSTimer循环引用问题

Block

什么是block

  • block是将函数及其执行上下文封装起来的对象

源码解析

  • 可以使用 ‘clang -rewrite-objc file.m’ 查看编译之后的文件内容

block截获变量特性

  • 局部变量:对于基本数据类型截获其值,对于对象类型连同所有权修饰符(strong/weak/_unsafe_unretained) 一起截获
  • 静态局部变量:以指针形式截获
  • 全局变量: 不截获
  • 静态全局变量: 不截获

__block修饰符

  • 一般情况下, 对被截获变量进行赋值操作需要添加__block修饰符
  • 静态局部变量, 全局变量, 静态全局变量不需要__block修饰符

block的内存管理


Objc

分类(category)


分类能够干啥:

  • 声明私有方法
  • 分解体积庞大的类文件
  • 拓展Framework的方法

分类中可以添加哪些内容?

  • 实例方法
  • 类方法
  • 协议
  • 属性(get set方法, 非实例变量)
  • 关联对象(伪成员变量)

特点:

  • 运行时决议
  • 分类方法会覆盖原类方法
  • 同名分类方法谁能生效取决于编译顺序
  • 名字相同的分类会引起编译报错

扩展(extension)

特点

  • 编译时决议
  • 只以声明的形式存在, 多数情况寄生于宿主类的.m中
  • 不能为系统类添加扩展

代理 (delegate)

  • 一种软件设计模式
  • iOS中以@protocol形式体现
  • 一对一
  • 一般声明为weak以规避循环引用

通知 (Notification)

  • 使用观察者模式来实现的用于跨层传递消息的机制
  • 传递方式一对多

KVO

  • 是观察者设计模式的又一实现
  • Apple使用了isa混写(isa-swizzling)来实现KVO
  • 使用setter方法改变值KVO才会生效
  • 使用setValue:forKey:改变值KVO才会生效
  • 成员变量直接修改需要手动添加KVO(基于KVC)才会生效

KVO

  • get
  • set

属性关键字

读写权限

  • readonly
  • readwrite

原子性

  • atomic
  • nonatomic

引用计数

  • retain/strong
  • assign/unsafe_unretained
  • weak
  • copy

assign特性

  • 修饰基本数据类型
  • 修饰对象类型时, 不改变引用计数
  • 会产生悬垂指针

weak特性

  • 不改变修饰对象的引用计数
  • 所指对象被释放后会自动置为nil

copy特性
浅拷贝: 引用计数+1
深拷贝: 开辟了新的内存空间

一些git常用命令

删除本地的单个分支

1
$ git branch -d [分支名]

删除远程的单个分支:

1
$ git push origin :[分支名] 或者 git push origin -d [分支名]

批量删除本地分支

1
$ git branch -a | grep 'feature_' | xargs git branch -D

批量删除远程分支

1
$ git branch -r | grep  'feature/*' | sed 's/origin\///g' | xargs -I {} git push origin :{}
  • git branch -r 查看远程分支
  • | sed ‘s/origin///g‘ 去掉origin(能够把接受到的分支都过滤掉开头的origin/得到实际的分支名 (大概这个意思))
  • -I {} 使用占位符来构造后面的命令
  • git push origin :branchName 删除远程分支

ffmpeg常用命令

提取文件中的视频

1
$ ffmpeg -i input.mp4 -vcodec copy -an v.mp4

提取文件中的音频

1
$ ffmpeg -i input.mp4 -vn -acodec copy a.m4a

提取文件中的mp3

1
2
$ ffmpeg -i input.mp4 -vn a.mp3
$ ffmpeg -i input.mp4 -vn -ar 44100 -ac 2 -ab 320 -f mp3 a.mp3

这里

  • -vn: 剔除输入文件中的视频
  • -ar: 设置输出mp3文件频率. 通常为 22050, 44100, 48000 Hz.
  • -ac: 设置音频通道数.
  • -ab: 设置音频码率.
  • -f: 设置输出文件格式. 这里为mp3

改变mp3文件的大小

1
$ ffmpeg -i input.mp3 -af 'volume=0.5' output.mp3

提取mp3文件中的指定时间音频

1
2
$ ffmpeg -i mc.mp3 -ss 00:00:00 -to 00:00:30 -acodec copy a2.mp3
$ ffmpeg -i mc.mp3 -ss 00:00:00 -t 30 -acodec copy a3.mp3

提取指定时间的视频

1
2
$ ffmpeg -i input.mp4 -t 00:00:30 -c copy part1.mp4 -ss 00:00:30 -codec copy part2.mp4
$ ffmpeg -i input.mp4 -ss 00:28:20 -to 00:30:38 -codec copy part.mp4

改变视频文件的分辨率

1
2
$ ffmpeg -i input.mp4 -filter:v scale=1280:720 -c:a copy output.mp4
$ ffmpeg -i input.mp4 -s 1280x720 -c:a copy output.mp4

合并视频与音频文件

1
2
3
$ ffmpeg -i a.m4a -i q1.mp4 -c copy av.mp4
$ ffmpeg -i input.mp4 -i input.mp3 -c:v copy -c:a aac -strict experimental output.mp4 (input.mp4中没音频)
$ ffmpeg -i input.mp4 -i input.mp3 -c:v copy -c:a aac -strict experimental -map 0:v:0 -map 1:a:0 output.mp4(input.mp4中可有音频)

拼接多个视频

将要合并的文件写入文件join.txt, 如下

1
2
file /home/genius/videos/video1.mp4
file /home/genius/videos/video2.mp4

执行以下命令

1
$ ffmpeg -f concat -safe 0 -i join.txt -c copy 3dav.mp4

截取视频指定时间的图像

1
$ ffmpeg -i input.mp4 -ss 10 -vframes 1 output.jpg

设置视频宽高比

1
$ ffmpeg -i input.mp4 -aspect 16:9 output.mp4

截取视频指定时间的系列图像

1
$ ffmpeg -i input.mp4 -r 1 -f image2 image-%2d.png

这里

  • -r: 帧率,默认25
  • -f: 输出文件格式, 这里为image
  • -image-%2d.png: 提取图片命名格式,这里文件将被命名为image-01.png, image-02.png等,如果是%3d, 则为image-001.png, image-002.png

截取视频指定时间的gif

1
$ ffmpeg -i input.mp4 -ss 10 -to 15 -s 640x320 -r 30 output.gif

给视频添加滤镜

1
$ ffmpeg -i input.mp4 -i logo.png -filter_complex "overlay=20:20" output.mp4

按照biterate压缩视频

1
$ ffmpeg -i input.mp4 -b:v 0.8M scaled.mp4

将图片合并成视频

  • 不带音频
    1
    ffmpeg -framerate 1 -pattern_type glob -i 'images/*.png' -c:v libx264 -profile:v high -crf 20 -pix_fmt yuv420p output.mp4