国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

直播流??內存優化?案

開發 架構
通?降低分辨率?式為采用圖片云開發系統提供的服務。在圖片 url 中加入分辨率的參數, 直接下載相應分辨率的圖?。分辨率的設置,以圖片清晰為標準,?般設置為展 示 ImageView 的大小。這樣不消耗客戶端的資源,不會給 CPU 帶來額外的工作。

01項目背景介紹

項目中直播流每場直播由一張直播圖片作為展示入口,用于提示用戶此直播的概要。如下圖: 

圖片圖片

然而直播圖片和容器的寬高比例出現不一致的情況。針對此情況,采取背景圖 contentmode展示為 aspectFill 且高斯模糊,上層高清圖為 aspectfit,給用戶一種圖片填滿且能清除獲取信息的視覺體驗。如下圖:

圖片圖片

然而服務端下發直播的圖片分辨率在1000 * 2000byte左右,占用內存大小為1000 * 2000 * 4,約為 2M 大小。資深直播用戶最多有一千場直播。使用 sd_webImage 下載圖片并緩存在內存中,查看足夠多的直播封面時,在iPhone 13機型,iOS15的手機,滑動到400場直播時,就會產生內存不足崩潰。且崩潰堆棧展示在進行高斯模糊的方法中。

02分析問題

經過初步分析,得出影響內存的原因有以下幾方面。

  • 圖片分辨率高,高斯模糊占用的內存越高。因為需要對進行大量模糊計算;
  • 用戶快速滑動直播流,正常的下載圖片速度會展示所有劃過的圖片,高斯模糊在圖片下載完成 block 中執行,即使劃過的直播圖,也會繼續高斯模糊直至返回。這樣會導致用戶大量無意義圖片占用大量內存;
  • 兩張 ImageView 需要在內存中加載兩張一樣的圖片,是一種內存浪費;
  • 為了用戶查看圖片的及時性和流暢性,項目中沒有設置存儲高斯模糊圖片最大占用內存。這會導致圖片內存只會在內存警告時被清除。導致高斯模糊不能獲取足夠的內存而崩潰;
  • 高斯模糊采用 vImage 方案,占用 CPU 進行高斯模糊計算,CPU 繁忙不能及時釋放內存,進一步加劇內存緊張。

03針對問題,采取措施

降低圖片分辨率

  • 通?降低分辨率?式為采用圖片云開發系統提供的服務。在圖片 url 中加入分辨率的參數, 直接下載相應分辨率的圖?。分辨率的設置,以圖片清晰為標準,?般設置為展 示 ImageView 的大小。這樣不消耗客戶端的資源,不會給 CPU 帶來額外的工作。

避免下載快速劃過的圖片


  • 判斷用戶是否快速劃過,無需下載圖片。scrollViewDidScroll 的回調頻率是小于 CADisplayLink 回調頻率的,在滾動緩慢的狀態下,離散取整可能導致 contentOffset 在某次刷新中不發生變化,也就是說 didScroll 的兩次打點間隔有一定可能大于0.0167s,是2個或者3個刷新周期。低速狀態下本身差值的差別就不大,所以使用 didScroll 打點,默認間隔是0.0167s即可。在 scrollviewDidScroll 中記錄兩次 scrollview 移動的差值,經實驗證明,速速大于60pt,流視圖圖片視覺上呈模糊狀態,故以60pt作為暴力滑動的臨界點;

  • 下一步,暴力滾動停止劃過圖片的下載。創建全局變量標記是否暴力滾動,在系統調用 cellForItem 方法時,判斷標記為是則不進行下載。非暴力滾動下,標記為否, cell 根據標記開啟下載當前的圖片;

  • 以上適用于自然減速停止的滑動。然而暴力滾動之后用戶手動突然停止,此時標記雖已及時改為否,但展示在屏幕上的圖片都處于不下載的狀態。我們在 scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate: 代理表示停止拖拽,在此時機,將展示在屏幕上的 cell 重新下載圖片。具體代碼如下:

    [self.collectionView.visibleCells  enumerateObjectsUsingBlock:^(__kindof UICollectionViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
              SVPGCLiveCollectionViewCell *cell = obj;
              if (!cell.yesToLoad) {
                  cell.yesToLoad = YES;
              }
      }];

    自定義 cell ,setYesToLoad方法中下載圖片,設置 yesToLoad為 Yes ,即可開啟下載當屏的圖片這種情況;

  • 其他的滑動情況:滾動到流頂部,手動設置 contenOffset:animated:經測試,滾動的速度屬于暴力滾動。需要在 scrollViewDidScrollToTop 和 scrollViewDidEndScrollingAnimation 中設置當屏圖片重新下載;

  • 內存存儲高斯模糊的容器為 NSCache ,NSCache 提供最大儲存值。根據直播 tab 業務需要,每屏展示的數量大約為15張左右。存儲的數值需比15張略大,保證頁面的流暢度。初設值為20,每張占用的內存在5M左右,20張存儲在100M,可接收范圍內;

  • 高斯模糊由 vImage 方式修改為 GPUImage 方式,使用 CPU 處理圖像, GPUImage 在 GPU 上處理 filter ,經統計,在 iOS13 上,處理圖片濾鏡時間比快約2倍。GPU 處理 filter 圖片需要運行大量 openGL 代碼,GPUImage 封裝了 openGL,只需要調用接口就可以實現 filter 。GPUImage 沒有現成的合成一張底部高斯,上層高清的圖片濾鏡。GPUImage 支持自定義頂點著色器和片元著色器實現濾鏡。整體思路為,使用混合濾鏡將高斯濾鏡的紋理和原圖紋理按照坐標計算生成新的輸出。紋理鏈條如圖:


a. 初始化高斯濾鏡,并設置參數。

GPUImageGaussianBlurFilter *gaussionfilter =     [[GPUImageGaussianBlurFilter alloc] init];
        gaussionfilter.blurRadiusInPixels = 9;//數值越高,越糊。
        [gaussionfilter forceProcessingAtSize:highDefiniImage.size];

說明:blurRadiusInPixels 決定高斯的卷積數。卷積數越高,模糊效果越明顯。forceProcessingAtSize:設置高斯過濾器的目標輸出分辨率

b. 初始始化原始圖?。GPUImage中靜態圖?的源對象為 GPUImagePicture類

GPUImagePicture *highImage = [[GPUImagePicture alloc] initWithImage:highDefiniImage];

通過傳?原圖的 image 對象?成 GPUImagePicture 。

c. 自定義頂點著色器和片元著色器創建自定義混合濾鏡。頂點著色器,是對頂點進行一系列操作的著色器,頂點除了有最基本的位置屬性,還包含其他屬性,比如紋理,法線等。通過頂點著色器,顯卡就知道頂點應該繪制在具體什么位置。針對每個頂點,頂點著色器都會執行一次。首先收到系統傳給他的數據(位置坐標),將數據處理成后續我們需要的數據。系統對頂點著色器輸出的頂點數據進行插值,并將插值結果傳遞給片段著色器。片段著色器根據插值結果計算最后屏幕上的像素顏色。 GPUImageTwoInputFilter 提供頂點著色器的代碼滿足需求,直接使用即可。頂點著色器的代碼如下所示:

NSString *const kGPUImageTwoInputTextureVertexShaderString = SHADER_STRING
(
 attribute vec4 position;
 attribute vec4 inputTextureCoordinate; //attribute  標注屬性為輸入變量,inputTextureCoordinate為第一個輸入對象的坐標
 attribute vec4 inputTextureCoordinate2; //inputTextureCoordinate2 為第二個輸入變量的坐標
 varying vec2 textureCoordinate; // varying 標注屬性為在vertex shader和fragment shader之間傳遞數據,表示將第一個輸入對象的坐標傳遞給片段著色器
 varying vec2 textureCoordinate2; //表示將第二個輸入對象的坐標傳遞給片段著色器
 void main()
 {
     gl_Position = position;
     textureCoordinate = inputTextureCoordinate.xy;
     textureCoordinate2 = inputTextureCoordinate2.xy;
 }
);

GPUImage 包裝頂點著色器為 string,便于加載。每一行代碼的作用標注在注釋里。片元著色器,是接收頂點著色器傳過來的數據,進行像素顏色計算。首先,需要傳入畫布和原圖的大小,用于計算畫布從原圖采點的坐標。其次,計算變量,我們需要確定上層高清圖在畫布上的leftX 和 rightX ,topY 和 bottomY,高度 targetH,寬度 targetW 。以及底部高斯背景圖片設置為 aspectFill 的高度和寬度。以上數值的計算涉及高清圖橫圖和豎圖。見下圖,左圖為豎圖,右圖為橫圖:

圖片圖片

相應代碼如下:

if (drawableW/drawableH > imageW/imageH ){//豎版
          targetW = imageW * (drawableH/imageH);

          lowp  float  left = (drawableW - targetW)/float(2);

          leftX = left/drawableW;

          rightX = (left+targetW)/drawableW;

          targetH = drawableH;

          bottomY = 1.0;

          targetHFill = imageHFill * drawableW / imageWFill;

          targetWFill = drawableW;
      }else{//橫版
          targetH = imageH * (drawableW/imageW);

          lowp float top = (drawableH - targetH)/float(2);

          topY = top/drawableH;

          bottomY = (top+targetH)/drawableH;

          targetW  = drawableW;

          rightX = 1.0;

          targetWFill = imageWFill * drawableH / imageHFill;

          targetHFill = drawableH;
      }

片元著色器通過 gl_FragColor = texture2D ( 參數1:輸?對象的紋理,參數2:輸入對象的坐標) 得到當前坐標的紋理。參數1由直接取值,參數2需要計算。坐標的計算分2種情況,?清圖和?斯背景,當畫布坐標處于 leftX 和 rightX , topY 和 bottomY 之間,則繪制?清圖,應取?清圖的相應坐標。相應坐標的計算為繪制的 點從畫布坐標換算到在?清圖上的坐標(坐標都為0-1區間值)如圖:

圖片圖片

目標為計算出高清圖的0.2,0.1。換算代碼如下:

if (textureCoordinate2.x >= leftX   && textureCoordinate2.x <= rightX && textureCoordinate2.y >= topY && textureCoordinate2.y <= bottomY) {
lowp  float offsetX = textureCoordinate2.x - leftX; //offsetx為圖中X的間距在畫布的占比。
lowp  float x = (offsetX * drawableW)/targetW; //X的距離在深灰高清圖中距離。
lowp  float offsetY = textureCoordinate2.y - topY;
lowp  float y = (offsetY * drawableH)/targetH;
}

由公式 offX* drawableW = x *targetW 左右兩邊都是 X 線段的實際距離,從而得出 x 的值。同理得出 Y 的值。當畫布的坐標落在上圖淺灰色區域,采點高斯。高斯展示方式為 aspectFill. 如下圖:

圖片圖片

粉色部分為高斯圖片的布局。高寬都會溢出被剪切一部分。圖中三角形為畫布中要繪制的點,此點在高斯圖中的位置為 targetY/targetHfill。targetY = (textureCoordinate2.y * drawableH + (targetHFill - drawableH )/float(2)) 為高斯圖被剪裁的上高度+畫布繪制點據畫布頂部的距離。具體代碼如下:

lowp   float  y = (textureCoordinate2.y * drawableH + (targetHFill - drawableH )/float(2))/ targetHFill;
lowp  float x = (textureCoordinate2.x * drawableW + (targetWFill - drawableW )/float(2))/ targetWFill;
gl_FragColor = texture2D(inputImageTexture, vec2(x, y));

x 的計算方式和 y 值相同。到此,片元著色器的工作完成。

d. GPUImage加載著色器,并返回 UIImage 對象。自此,一張高斯背景疊加高清的圖片生成了。在直播流中,不止有一張需要合成,且合成是較耗時操作,需將合成操作放在子線程異步執行。執行完成后同步回到主線程展示。

e. 在使用 GPUImage 時,有?個需要注意的地?。GPUImage 底層使?的 是 openGL , openGL 在后臺進行渲染會導致 app 崩潰。所以需要我們退出后臺時,停止 openGl 渲染。采取的方式有三種,第?種,將合成隊列在退出后臺前設 置 suspend = yes ,還未開始的合成任務將不再執行,直至進入前臺后設 置 suspend = no 。然而,這種方式不能規避還在進行中的任務。于是第?種,?定 義 NSOperation ,執? operation 時。系統會調用 NSOperation 的 main 函數, 在 main 函數中,寫實現代碼。在每?句實現代碼前都判斷是否 cancled 。如果 cancled ,直接 return 。在系統即將進?后臺時,將在運行的任務 cancle 掉, operation 繼續執行,監測到已經 cancle 了,就會 return 。然而,粒度還是不夠細。如果任務執行到最后一行,且最后一行有 openGL 操作,那么就會攔截不到。第三種, GPUImage 的渲染都是放在??的?個隊列同步執?,在接收到系統將進入后臺的通知中,加入渲染隊列?個同步空任務,則系統會執行完空任務前的所有 任務之后,再進入后臺。從而避免后臺渲染。

自此,多張合成圖片的方案就結束了,結合線上數據,本頁內存消耗節約10M左右,每張合成圖片時間節約8ms左右。

責任編輯:武曉燕 來源: 搜狐技術產品
相關推薦

2018-07-23 09:26:08

iOS內存優化

2017-02-14 17:00:39

iOSApp內存優化

2010-05-13 10:47:44

MySQL數據庫查詢

2010-05-21 13:48:36

MySQL數據庫

2022-07-20 22:55:39

直播OOM抖動

2010-08-10 10:00:57

Flex內存

2010-08-10 10:17:44

Flex內存

2011-07-28 10:01:19

IOS 內存優化

2011-08-10 09:06:44

內存內存優化

2010-06-17 09:15:02

MySQL數據庫查詢

2010-06-11 12:32:57

MySQL數據庫查詢

2025-10-24 10:00:00

2017-03-14 18:48:06

Android性能優化內存優化

2013-09-16 16:56:09

AndroidBitmap內存優化

2025-12-01 01:48:00

2022-07-05 08:41:03

Redis保存大數據

2023-11-03 17:02:18

抖音直播畫質優化

2021-11-23 16:00:56

DevOps價值流價值流優化

2015-09-16 15:21:23

Android性能優化內存

2017-12-14 14:32:30

.Net內存代碼
點贊
收藏

51CTO技術棧公眾號

欧美精品一区二区免费| 亚洲自拍另类| 黄色免费视频大全| 日韩视频永久免费观看| 成人久久久精品乱码一区二区三区| 国产深夜视频在线观看| 国产亚洲一区在线播放| 欧美高清性hdvideosex| 视频一区视频二区中文字幕| 麻豆av在线免费观看| 亚洲巨乳在线观看| 蜜臀在线免费观看| www.国产精品一二区| 一区二区欧美在线观看| 国产精品日韩欧美一区| av成人免费看| 国产在线网站| 日本成人黄色网| 国产精品一二三在线观看| 91在线播放国产| 搡老女人一区二区三区视频tv| 一区二区三区日韩精品视频| 国产午夜精品一区二区三区欧美| 午夜免费视频在线国产| 亚洲高清123| 国精产品一区一区三区有限在线| 蜜桃一区二区三区在线观看| 中文字幕久热精品在线视频| 亚洲人成亚洲人成在线观看图片| 国产亚洲综合在线| 主播福利视频一区| 亚洲五月综合| 性欧美1819sex性高清大胸| 一本—道久久a久久精品蜜桃| 视频一区视频二区国产精品| 欧美国产一区二区在线观看| 欧美大片专区| 中文字幕在线官网| 成人蜜桃视频网站网址| 国产成人精品一区二区三区福利| 亚洲国产精品字幕| 天堂资源在线中文精品| 欧美国产三级| 午夜免费一区| 久久99高清| 美女视频免费精品| 色狠狠一区二区三区| 四虎影院观看视频在线观看 | 青青久久av北条麻妃黑人| 精品一区电影国产| 欧美美女视频在线观看| 欧美一区二区三区精品| 亚洲精品欧美激情| 伊人精品视频| 欧美日韩女优| 福利在线导航136| 亚洲综合伊人| 丝袜国产日韩另类美女| 亚洲欧美成人在线| 国产麻豆精品95视频| 亲子伦视频一区二区三区| 日本在线观看| 久久精品国产清自在天天线| 国产精品丝袜一区| 国产亚洲高清视频| 一本色道69色精品综合久久| 婷婷在线视频| 成人在线观看a| 国产伦理一区二区三区| 欧美久久精品午夜青青大伊人| 在线精品视频一区二区三四| 26uuu国产日韩综合| 亚洲精品欧美| 成人台湾亚洲精品一区二区| 免费污视频在线| 午夜在线免费视频| 国产成人在线小视频| 国产高清精品一区二区| 久久久久久亚洲精品| 亚洲福利视频网| 狠狠色狠色综合曰曰| 337p粉嫩大胆噜噜噜噜噜91av | 欧美一区二区三区久久精品| 亚洲精品69| 污污的网站在线看| 在线免费色视频| 激情视频综合网| 亚洲欧美丝袜| 国产精品一区二区三区免费视频 | 欧美精品免费在线观看| 91精品福利在线一区二区三区| 国产精品麻豆欧美日韩ww| 老司机午夜精品| 国产一区视频在线观看免费| 欧美国产极品| 精品三级在线| 精精国产xxxx视频在线中文版 | 日韩视频网站在线观看| 日本一区视频在线观看免费| 韩国精品久久久999| 日韩精品视频在线观看免费| 欧美视频三区在线播放| 亚洲激情图片小说视频| 成人看片黄a免费看在线| 日韩福利视频网| 欧美性色综合| 日韩精品dvd| 欧美电影在线观看免费| www999久久| 欧亚一区二区| 三级在线观看视频| 尤物yw193can在线观看| 成人jjav| 亚洲精品视频区| 国产视频二区| 99re在线视频播放| 国产v亚洲v天堂无码久久久| 国产自产在线视频| 国产精品无码乱伦| 福利一区二区在线| 亚洲天堂av在线免费观看| 亚洲欧洲精品一区二区三区波多野1战4| 亚洲猫色日本管| 久久久久久日产精品| 成人av资源在线| 丁香婷婷综合网| 国产成人在线观看免费网站| 麻豆精品在线播放| 人人狠狠综合久久亚洲| 日韩中文字幕亚洲一区二区va在线 | 国产一区二区黑人欧美xxxx| 精品福利视频一区二区三区| 日韩欧美在线不卡| 91精品福利在线一区二区三区| 欧美日韩国产乱码电影| 欧美日韩在线一区二区| 精品视频在线免费观看| 欧美日本在线播放| 欧美一区二区三区播放老司机| 欧美一区二区三区系列电影| 亚洲激情专区| 国产精品久久久久无码av| 羞羞答答成人影院www| 国户精品久久久久久久久久久不卡| 91精品一区二区三区综合在线爱| 欧美ab在线视频| 尤物精品在线| 日韩国产在线观看| 国产自产2019最新不卡| 丰满岳乱妇一区二区三区| 欧美成人一区二区在线| 黄色漫画在线免费看| 欧美视频在线观看 亚洲欧| 久久女同精品一区二区| 国产欧美日韩精品a在线观看| 国产精品视频你懂的| 亚洲欧洲综合另类| 午夜激情综合网| 欧美日本高清视频在线观看| 91精品国产品国语在线不卡 | 日韩伦理视频| 亚洲小说欧美另类社区| 蜜桃视频在线一区| 成人av网在线| 亚洲欧美日韩电影| 欧美综合一区二区三区| 亚洲精品一区二区三区福利| 在线看福利67194| 午夜精品久久久久久久男人的天堂 | 中文字幕中文乱码欧美一区二区| 亚洲免费在线看| 色综合激情五月| 欧美一二三四在线| 一区二区三区国产视频| 97视频免费在线观看| 91精品黄色| 在线播放 亚洲| 久久综合伊人77777麻豆最新章节| 嫩模私拍啪啪| 欧美日韩视频在线播放| 成人精品高清在线视频| 国产成人短视频在线观看| 国产欧美日韩一区二区三区在线| 国产精品99久久久久久似苏梦涵 | 色成人综合网| 日韩在线黄色| 亚洲一本视频| 国产精品一二三四五| 中文字幕一区二区三区四区 | 欧美片网站yy| 色噜噜久久综合伊人一本| 国产精品7m视频| 日本成人三级| 污污动漫在线观看| 国产成人l区| 一区二区三区四区高清视频| 午夜欧美精品| www.欧美精品一二区| 午夜精品久久久久久| 国产偷亚洲偷欧美偷精品|