视频播放器本地代理服务设计

场景

希望在播放视频的时候能边下边播。而不是等整个视频下好才能播
缓存视频,对于播放过的视频能缓存住,下次不从网络获取,节省流量带宽。用户随意拖动进度条的部分也能缓存住。
控制下载进度,用户只看了前面一点并暂停了,那么没必要整个视频都下下来。

方案

播放器Manager主要给项目使用,提供一些简洁的接口,屏蔽所有能屏蔽的细节。
播放器kit层是对播放器SDK简洁的封装,方便使用。播放器SDK基于 ffmpeg 写的独立的一个SDK。
本地server是一个http代理服务,本文将描述这个模块。
另外,播放器日志监控,数据统计由另外的统计SDK做了,没放在这里做。

首先,播放器SDK并不直接去连接视频服务器,而是先连接本地server,然后由本地server去连接视频服务器,本地server收到服务端的视频数据,再转发给播放器,相当于一个转发的功能。不断接收来自播放器的请求,然后去下载数据,然后再返回给播放器。


Server模块:
接收请求和下发数据,都使用同步非阻塞IO模式。
接收数据:使用kqueue多路复用接收IO请求。
下发数据:同步非阻塞模式下发(开一个线程下发数据,每个数据之间是同步的)
unix 上的 kqueue 有个坑,无法监测socket发送缓存区由满变到不满的状态,但 linux 的 epoll 可以
完整的缓冲区状态变化需要4个,满 -> 不满,不满 -> 满,空 -> 非空,非空 -> 空

Downloader模块:
会收到来自Server的请求,内容是视频的(url + offset)
下载前会检查缓存,如果有缓存直接下发缓存的数据,没有缓存才去下载。
使用 NSURLSession 下载,NSURLSession 的每一个 task 会创建worker线程去下载数据。
worker 返回一段数据,把数据发给 server 去下发。server下发失败关闭这个 task。
worker 同时也把数据发给 Cache 模块去缓存。

Cache模块:
会收到来自Downloader的读取和写入请求,内容都是(url, offset, length)
(url, offset, length)能确定唯一一个视频的块。

取视频url作为缓存的key。
一个视频逻辑上被分成 512k 为一个块存储,chunk_size = 512k。
例如一个视频有1224k, 被分成 512k + 512k + 200k,3块,每个块对应一个文件。

如下图,key + offset + totalLength 作为文件名,file_size 就是 chunk_size

读取缓存:
读取以块(512k)为单位。
内存有就内存返回,内存没有就上磁盘查找,找到就返回。
用户可能任意拖动进度条,那么 offset 可能是任意值,读取缓存的时候,就看offset对应的块存不存在,存在就返回,不存在就不返回,得重新下载了。

用NSData读取磁盘数据,它底层使用了 mmap,省掉了系统内核空间到用户空间的拷贝,速度快。

写入缓存:
写入缓存按照 512k 为一块写入。最坏的情况如下图:

用户刚好拖动到进度条到50k,然后下到1000k,他就停止播放。那么差不多 1MB 的数据缓存不了,因为第0块不满,第1块也不满。
最好的情况就是从0看起,看到刚好满足块的地方,全部能缓存。
网络好可以增大chunk_size,网络差可以减小chunk_size。减少不能缓存的情况。

用户频繁拖动进度条,产生很多零碎的块,现在内存中保存中,拼接够了一个512k的块,再写入文件。
零碎的块类似这样:
(url, offset, length)
(url, 0, 100),(url, 50, 150),(url, 12345, 1234),(url, 10000, 10)
块有重叠的地方,每收到一个写任务,就要去判断是否有重叠,有重叠需要合并一下。
比如现在有 (url, 0, 100)
收到一个(url, 50, 150)
发现 50 在 0 到 100 之间,那么合并为 (url, 0, 200)
如果合并后满足了一个块的范围,那么把这个块写文件记录。

缓存淘汰:
假定用户经常看的视频不能优先淘汰。那么用 LRU 淘汰策略即可,每个缓存块设置一个count,缓存命中一次就 count++,触发淘汰的时候,把 count 最小的先淘汰.

流量控制

用户只看了视频前面一点,就暂停了,那么后面的视频不再下载。
即播放器的消费速度比本地server的生产速度要慢。
播放器设置为5MB的缓存大小,用户暂停后,缓冲区肯定会占满,然后播放器不在recv()数据,那么server下发数据会报 EAGAIN 写缓存区满的错误,这个时候每隔3秒重试一次下发。设置为3秒重试是因为假设了5MB视频能够播放3秒。

如果播放器的消费速度比本地server的生产速度要快,那有可能是网速太慢了。

完。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容