iOS彈幕解決方案——HJDanmaku 2.0發(fā)布

轉(zhuǎn)載請注明出處:http://www.olinone.com/

Hi,好久不見,HJDanmaku 1.0版本發(fā)布已經(jīng)過去兩年之久,直播行業(yè)的快速崛起催生了直播彈幕的迫切需求德撬,高并發(fā)、大流量躲胳、實時性的特性和以往視頻彈幕的場景都大有不同蜓洪,為了滿足新的直播業(yè)務(wù)場景,HJDanmaku2.0正式發(fā)布坯苹!

流暢度

相較于1.0版本隆檀,HJDanmaku2.0采用全新的異步渲染引擎,98%的計算工作轉(zhuǎn)移到子線程執(zhí)行粹湃,避免了主線程的卡頓延時恐仑。同時,參考離屏渲染技術(shù)为鳄,將組裝彈幕和渲染彈幕分布在兩個獨立線程異步執(zhí)行裳仆,確保了彈幕渲染的流暢性

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{

? ? NSArray *danmakuAgents = [self.danmakuSource fetchDanmakuAgentsForTime:(HJDanmakuTime){HJMaxTime(time), time.interval}];

? ? dispatch_async(_renderQueue, ^{

? ? ? ? if (danmakuAgents.count > 0) {

? ? ? ? ? ? [self.danmakuQueuePool insertObjects:danmakuAgents atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, danmakuAgents.count)]];

? ? ? ? }

? ? });

}];

[self.sourceQueue cancelAllOperations];

[self.sourceQueue addOperation:operation];

將組裝彈幕的過程拆分為獨立的子線程任務(wù),統(tǒng)一由NSOperationQueue單執(zhí)行隊列管理济赎,有效的降低CPU的使用率鉴逞,提升系統(tǒng)運行穩(wěn)定性。此外司训,在2.0版本中,使用CADisplayLink替換定時器NSTimer液南,與屏幕刷新頻率保持一致壳猜,可以避免NSTimer由于線程阻塞導(dǎo)致的刷新延時

高并發(fā)

直播與傳統(tǒng)視頻最大區(qū)別在于其實時性,短時間大量的彈幕發(fā)送對底層渲染引擎是個不小的挑戰(zhàn)滑凉。為了解決這個問題统扳,HJDanmaku2.0引入數(shù)據(jù)源Source的思想喘帚,將彈幕接收與組裝的過程分開,可以針對直播咒钟、視頻場景實現(xiàn)差異化的處理方案吹由。視頻場景對時間精確度要求較高,涉及到彈幕的時間排序朱嘴,同時倾鲫,播放進度回放也需要數(shù)據(jù)源保存所有的彈幕數(shù)據(jù)。直播場景則比較單一萍嬉,播放完可以立刻釋放乌昔,避免內(nèi)存的過度消耗

u_int interval = 100;

NSMutableArray *danmakuAgents = [NSMutableArray arrayWithCapacity:interval];

NSUInteger lastIndex = danmakus.count - 1;

[danmakus enumerateObjectsUsingBlock:^(HJDanmakuModel *danmaku, NSUInteger idx, BOOL *stop) {

? ? HJDanmakuAgent *agent = [[HJDanmakuAgent alloc] initWithDanmakuModel:danmaku];

? ? [danmakuAgents addObject:agent];

? ? if (idx == lastIndex || danmakuAgents.count % interval == 0) {

? ? ? ? OSSpinLockLock(&_spinLock);

? ? ? ? [self.danmakuAgents addObjectsFromArray:danmakuAgents];

? ? ? ? OSSpinLockUnlock(&_spinLock);

? ? ? ? [danmakuAgents removeAllObjects];

? ? }

}];

通過拆分入庫數(shù)據(jù)分布添加可以避免線程鎖的長時間占有,提升系統(tǒng)的穩(wěn)定性和流暢度

精確度

與1.0版本不同壤追,新版本通過toleranceCount維度判斷彈幕是否過期磕道,默認(rèn)允許最大2秒誤差。彈幕刷新頻率為0.5秒行冰,即每個彈幕有效等待次數(shù)為2/0.5 = 4次溺蕉,超過4次沒有渲染將自動丟棄

- (void)removeExpiredDanmakusForTime:(HJDanmakuTime)time {

? ? [self.danmakuQueuePool enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(HJDanmakuAgent *danmakuAgent, NSUInteger idx, BOOL *stop) {

? ? ? ? danmakuAgent.toleranceCount --;

? ? ? ? if (danmakuAgent.toleranceCount <= 0) {

? ? ? ? ? ? [self.danmakuQueuePool removeObjectAtIndex:idx];

? ? ? ? }

? ? }];

}

彈幕冗余度的設(shè)計使得彈幕顯示更加平均,優(yōu)化了彈幕顯示效果悼做,但是會降低彈幕顯示的精確度焙贷,特別對于視頻場景,相對于1.0版本有所下降贿堰,如果你對精確度要求較高辙芍,可以降低tolerance冗余值

碰撞檢測

與1.0相同,HJDanmaku2.0仍然使用系統(tǒng)動畫的方式提供彈幕動畫支持羹与,但是碰撞檢測方式略有不同

- (BOOL)checkLRIsWillHitWithPreDanmaku:(HJDanmakuAgent *)preDanmakuAgent danmaku:(HJDanmakuAgent *)danmakuAgent {

? ? CGFloat width = CGRectGetWidth(self.bounds);

? ? CGFloat preDanmakuSpeed = (width + preDanmakuAgent.size.width) / self.configuration.duration;

? ? if (preDanmakuSpeed * (self.configuration.duration - preDanmakuAgent.remainingTime) < preDanmakuAgent.size.width) {

? ? ? ? return YES;

? ? }

? ? CGFloat curDanmakuSpeed = (width + danmakuAgent.size.width) / self.configuration.duration;

? ? if (curDanmakuSpeed * preDanmakuAgent.remainingTime > width) {

? ? ? ? return YES;

? ? }

? ? return NO;

}

HJDanmaku2.0中故硅,碰撞檢測不再以彈幕時間點為參考維度,渲染的彈幕擁有剩余時間屬性纵搁,通過剩余時間與速度的關(guān)系即可判斷兩者之間是否碰撞吃衅。同時,2.0版本只在添加彈幕和恢復(fù)動畫時為彈幕視圖添加動畫腾誉,其它時間不再校驗

手勢

運動視圖系統(tǒng)默認(rèn)無法響應(yīng)手勢交互事件徘层,整個點擊事件交由全局統(tǒng)一處理。HJDanmakuCell定義屬性selectionStyle控制彈幕能否點擊利职,默認(rèn)HJDanmakuCellSelectionStyleNone趣效,即不能點擊

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

? ? self.selectDanmakuAgent = nil;

? ? HJDanmakuAgent *danmakuAgent = [self danmakuAgentAtPoint:point];

? ? if (danmakuAgent) {

? ? ? ? if (danmakuAgent.danmakuCell.selectionStyle == HJDanmakuCellSelectionStyleDefault) {

? ? ? ? ? ? self.selectDanmakuAgent = danmakuAgent;

? ? ? ? ? ? return self;

? ? ? ? }

? ? ? ? CGPoint cellPoint = [self convertPoint:point toView:danmakuAgent.danmakuCell];

? ? ? ? return [danmakuAgent.danmakuCell hitTest:cellPoint withEvent:event];

? ? ?}

? ? ?return [super hitTest:point withEvent:event];

}

視圖整體響應(yīng)鏈參考以上代碼,當(dāng)收到點擊事情時猪贪,優(yōu)先判斷彈幕cell是否響應(yīng)跷敬,如果響應(yīng)則交由彈幕cell處理,否則交由全局統(tǒng)一處理

總結(jié)

時隔兩年热押,HJDanmaku2.0在性能西傀、并發(fā)以及定制型方面都有較大的提升斤寇,以iphone6設(shè)備測試為例,CPU整體使用率穩(wěn)定在5%左右拥褂,大并發(fā)100條/秒彈幕的持續(xù)輸入娘锁,F(xiàn)PS可以維持在55幀以上

目前暫時支持OC,swift版本正在開發(fā)中饺鹃,如果你有意貢獻swift代碼莫秆,可以與我聯(lián)系~

當(dāng)然,如果你喜歡尤慰,可以為本項目點點贊


寫在文后:

新建了一個iOS開發(fā)QQ交流群(首頁右上角入群)馏锡,歡迎廣大iOS開發(fā)朋友一同交流學(xué)習(xí)。當(dāng)然伟端,你也可以Follow本人GitHub杯道,或者關(guān)注我的新浪微博,感謝你的來訪责蝠,下期再見党巾!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市霜医,隨后出現(xiàn)的幾起案子齿拂,更是在濱河造成了極大的恐慌,老刑警劉巖肴敛,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件署海,死亡現(xiàn)場離奇詭異,居然都是意外死亡医男,警方通過查閱死者的電腦和手機砸狞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來镀梭,“玉大人刀森,你說我怎么就攤上這事”ㄕ耍” “怎么了研底?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長透罢。 經(jīng)常有香客問我榜晦,道長,這世上最難降的妖魔是什么琐凭? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任芽隆,我火速辦了婚禮,結(jié)果婚禮上统屈,老公的妹妹穿的比我還像新娘胚吁。我一直安慰自己,他們只是感情好愁憔,可當(dāng)我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布腕扶。 她就那樣靜靜地躺著,像睡著了一般吨掌。 火紅的嫁衣襯著肌膚如雪半抱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天膜宋,我揣著相機與錄音窿侈,去河邊找鬼。 笑死秋茫,一個胖子當(dāng)著我的面吹牛史简,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肛著,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼圆兵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了枢贿?” 一聲冷哼從身側(cè)響起殉农,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎局荚,沒想到半個月后超凳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡耀态,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年轮傍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片茫陆。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡金麸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出簿盅,到底是詐尸還是另有隱情挥下,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布桨醋,位于F島的核電站棚瘟,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏喜最。R本人自食惡果不足惜偎蘸,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迷雪,春花似錦限书、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赁严,卻和暖如春扰柠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疼约。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工卤档, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人程剥。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓劝枣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親倡缠。 傳聞我的和親對象是個殘疾皇子哨免,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容

  • HJDanmaku 1.0版本發(fā)布已經(jīng)過去兩年之久,直播行業(yè)的快速崛起催生了直播彈幕的迫切需求昙沦,高并發(fā)琢唾、大流量、實...
    蘋果上的小豌豆閱讀 708評論 0 1
  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗盾饮。 張土汪:刷leetcod...
    土汪閱讀 12,745評論 0 33
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理采桃,服務(wù)發(fā)現(xiàn),斷路器丘损,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • 2017.02.22 可以練習(xí)普办,每當(dāng)這個時候,腦袋就犯困徘钥,我這腦袋真是神奇呀衔蹲,一說讓你做事情,你就犯困呈础,你可不要太...
    Carden閱讀 1,346評論 0 1
  • 概述在iOS開發(fā)中UITableView可以說是使用最廣泛的控件舆驶,我們平時使用的軟件中到處都可以看到它的影子,類似...
    liudhkk閱讀 9,047評論 3 38