器之心發布
機器之心編輯部
聯合視頻專家組 JVET 官網顯示,字節跳動設立在美國的研發團隊于今年初發起了一項視頻壓縮技術提案,并命名為 DAM(Deep-filtering with Adaptive Model-selection)。相比 H.266/VVC 最新標準,DAM 能夠為視頻編碼性能帶來顯著提升,亮度信號 Y 可實現 10.28% 的性能增益。兩個色度信號 U 和 V 的性能增益也分別達到 28.22% 和 27.97%。這是業界公開的單個智能編碼工具的最佳性能增益。
視頻編解碼是視頻應用的底層核心技術,作用是對圖像進行壓縮和數字編碼,以盡可能小的帶寬傳送盡可能高質量的視頻數據。H.264 是現在被廣泛使用的視頻編解碼標準,在同等視頻質量下,H.265/HEVC 標準可以讓視頻體積減小一半。H.265 尚未完全普及,新一代標準 H.266/VVC 比 H.265 讓視頻又減小一半。
這并不是視頻編碼技術的盡頭。
今年初,字節跳動先進視頻團隊(AVG)向聯合視頻專家組 JVET 發起了一項 JVET-U0068 技術提案,可以為視頻壓縮的三個顏色分量(Y, U, V)分別實現約 10%、28%、28% 的性能增益,這是業界公開的單個智能編碼工具的最佳性能增益。在優化壓縮質量的同時,視頻體積相比 H.266 最新標準至少還可以縮小 13%。就其實際效果而言,如果新技術得以應用,與現在主流的 H.264 標準相比,我們看同樣質量的視頻,大約只需要 22% 的帶寬和存儲空間。
這項技術名為 DAM(Deep-filtering with Adaptive Model-selection),它是通過深度學習技術構建減少視頻壓縮失真的濾波器,主干是基于殘差單元堆疊的深度卷積神經網絡,輔以自適應模型選擇以最大程度適應特性復雜的自然視頻。該技術由字節跳動 AVG 的美國加州研發團隊實現,成員來自高通、英特爾、微軟等巨頭以及海內外多家頂級院校。
我們先從下圖示例中對比 H.264 與 H.266+DAM 的視頻壓縮效果:
可以看到,相同壓縮比條件下,H.266+DAM 編碼壓縮質量遠遠優于 H.264。
除了視頻壓縮質量提升之外,應用 DAM 技術可以比H.266再縮小 13% 的數據體積,以下圖片來自國際標準組織的測試視頻。其中,圖(左)為原圖,每像素 12 字節;圖(中)使用 VTM11.0 壓縮(qp=42),每像素 0.00216字節,峰值信噪比 27.78dB;圖(右)使用 VTM11.0+DAM(qp=42),每像素 0.00184 字節,峰值信噪比 28.02dB。
對比圖(中)和圖(右)可以看出,應用 DAM 技術后,圖(右)壓縮比更高,峰值信噪比(客觀質量)更好,主觀質量也相對更好。
圖1. 左:原圖, 12bpp,中:VTM-11.0壓縮,QP42,0.00216bpp,27.78dB,右:VTM-11.0+DAM,QP42, 0.00184bpp,28.02dB
技術細節
DAM 的構建方法
提案 JVET-U0068 所介紹的 DAM 是字節跳動 AVG 此前一項提案 JVET-T0088 的擴展版本。
在具體實現上,為了減輕深度網絡的訓練難度,DAM 算法利用殘差單元作為基本模塊,并多次堆疊來構建最終網絡。所謂殘差單元是指通過引入跳層連接,允許網絡把注意力放在變化的殘差上。為了處理不同類型的內容,新技術針對不同類型的 slice 和質量級別訓練不同網絡。此外,還引入了一些新特性來提高編碼性能。
圖 1:(a)是卷積神經網絡濾波器的架構,M 代表特征圖的數量,N 代表特征圖的空間分辨率;(b)是(a)中殘差塊的結構。
DAM 濾波方法的主干如上圖 1 所示,為了增加感受野,降低復雜度,此方法包含一個步幅為 2 的卷積層,該層將特征圖的空間分辨率在水平方向和垂直方向都降低到輸入大小的一半,這一層輸出的特征圖會經過若干順序堆疊的殘差單元。最后一個卷積層以最后一個殘差單元的特征圖作為輸入,輸出 4 個子特征圖。最后,shuffle 層會生成空間分辨率與輸入相同的濾波圖像。
與此架構相關的其他細節如下:
新特性:自適應模型選擇
在 JVET-T0088 的卷積神經網絡結構基礎上,JVET-U0068 引入了以下幾種新特性:
在線推斷及訓練
推斷過程中使用 PyTorch 在 VTM 中執行 DAM 深度學習的在線推斷,下表 1 是根據 JVET 建議給出的網絡信息:
表 1。
訓練過程中以 PyTorch 為訓練平臺,采用 DIV2K 和 BVI-DVC 數據集,分別訓練針對 intra slice 和 inter slice 的卷積神經網絡濾波器,并且訓練不同的模型以適應不同的 QP 點,訓練階段的網絡信息根據 JVET 建議列于下表 2 中。
注意,當訓練 inter slice 濾波器時,預測信息也被用作輸入,而在 JVET-T0088 中,它僅用于 intra slice。
表 2。
下圖 2 給出了訓練集和驗證集損失函數的一個示例。
圖 2。
實驗結果:三個顏色分量(亮度 Y 和色度 Cb、Cr)性能增益顯著
考慮到 VTM-9.0 和 VTM-10.0 之間的微小差異,并根據 JVET 定義的常規測試條件,在 VTM-9.0 上測試了字節跳動 AVG 的 DAM 技術提案,測試結果如下表 3 和表 4 所示。
結果顯示,在 RA 構型下,Y、Cb 和 Cr 的 BD-rate 節省分別為 10.28%、28.22% 和 27.97%;在 AI 配置下,對 Y、Cb 和 Cr 分別可帶來 8.33%、23.11% 和 23.55% 的 BD-rate 節省。
表 3:AVG 提案在 VTM9.0(RA)上的性能表現。
表 4:AVG 提案在 VTM9.0(AI)上的性能表現。
總結
實測證明,字節跳動 AVG 的這項視頻編碼技術創新,可以讓視頻的數據體積相比 H.266 最新國際標準再縮小 13%。對視頻服務商來說,存儲和帶寬成本將顯著降低;對用戶來說,在網速較慢的情況下也可以流暢觀看高清視頻。
但正如前文所述,早在 2013年正式通過的 H.265,如今還沒有完全普及。一方面,高昂的專利授權費用導致生產硬件設備和生產內容的廠商無法承擔,用戶也只能買并不支持 H.265 標準的設備;另一方面,H.265 的專利收費很復雜,想要使用 H.265 得分別多次繳專利費。因此,目前最常見的還是 18 年前的 H.264 標準。
盡管 H.266 新一代標準的推廣還有很長的路要走,字節跳動 AVG 的技術探索并不會停止,其研究成果也會通過自主研發的 BVC 編碼器投入應用,為抖音、西瓜視頻、等 App 的視頻類內容處理,以及云計算、云游戲等基礎架構領域創造更高清畫質、更流暢播放的視頻體驗。
ue.js 的核心是一個響應的數據綁定系統,它允許我們在普通 HTML 模板中使用特殊的語法將 DOM “綁定”到底層數據。被綁定的DOM 將與數據保持同步,每當數據有改動,相應的DOM視圖也會更新。基于這種特性,通過vue.js動態綁定class就變得非常簡單。
思路:以某一頁面樣式需要單獨適配iphonex為例
方式一.對象的形式(第一個參數 類名, 第二個參數:boolean值) :class="{'footer':isIphoneX}"
//某一頁面適配iPhone X <div class="bottom" :class="{'footer':isIphoneX}"> </div> data () { return { isIphoneX:false } }, mounted () { if(window.screen.width==375&&window.screen.height==812){ this.isIphoneX = true }
渲染后的
渲染后的HTML: <div class="bottom footer"> </div>
如圖:
image
優點:以對象的形式可以寫多個,用逗號分開 <div :class="{'p1' : false, 'p': true}"></div>
方式二.三元表達式(放在數組中,類名要用引號) :class="[isIphoneX ? 'bottom' : 'footer']"
//某一頁面適配iPhone X <div :class="[isIphoneX ? 'bottom' : 'footer']"> </div>
渲染后:
渲染后的HTML: <div class="footer"> </div>
image.gif
如圖:
image
**方式三.動態數組里的變量 **:class="[isTrue, isFalse]"
//某一頁面適配iPhone X <div :class="[{'footer':isIphoneX} , 'bottom']"> </div>
渲染后和方法一是一樣的。vue數據和class都符合雙向綁定的規則!
omcat是什么?
Tomcat是開源的 Java Web 應用服務器,實現了 Java EE 的部分技術規范,比如 Java Servlet、Java Server Page、JSTL、Java WebSocket。Java EE 是 Sun 公 司為企業級應用推出的標準平臺,定義了一系列用于企業級開發的技術規范。除了上述的之外,還有 EJB、Java Mail、JPA、JTA、JMS 等,而這些都依賴具體容器的實現。
上圖對比了 Java EE 容器的實現情況,Tomcat 和 Jetty 都只提供了 Java Web 容器必需的 Servlet 和 JSP 規范,開發者要想實現其他的功能,需要自己依賴其他開源實現。
Glassfish 是由 sun 公司推出,Java EE 最新規范出來之后,首先會在 Glassfish 上進行實現,所以是研究 Java EE 最新技術的首選。
最常見的情況是使用 Tomcat 作為 Java Web 服務器,使用 Spring 提供的開箱即用的強大功能,并依賴其他開源庫來完成負責的業務功能實現。
Servlet容器
Tomcat 組成
如下圖所示,主要有 Container 和 Connector 以及相關組件構成。
Container組成
生命周期管理
Tomcat 為了方便管理組件和容器的生命周期,定義了從創建、啟動、到停止、銷毀共 12 種狀態
tomcat 生命周期管理了內部狀態變化的規則控制,組件和容器只需實現相應的生命周期方法,即可完成各生命周期內的操作(initInternal、startInternal、stopInternal、 destroyInternal);
比如執行初始化操作時,會判斷當前狀態是否 New,如果不是則拋出生命周期異常;是的話則設置當前狀態為 Initializing,并執行 initInternal 方法,由子類實現,方法執行成功則設置當前狀態為 Initialized,執行失敗則設置為 Failed 狀態;
Tomcat 的生命周期管理引入了事件機制,在組件或容器的生命周期狀態發生變化時會通知事件監聽器,監聽器通過判斷事件的類型來進行相應的操作。事件監聽器的添加可以在 server.xml 文件中進行配置;
Tomcat 各類容器的配置過程是通過添加 listener 的方式來進行的,從而達到配置邏輯與容器的解耦。如 EngineConfig、HostConfig、ContextConfig。
Tomcat 的啟動過程
啟動從 Tomcat 提供的 start.sh 腳本開始,shell 腳本會調用 Bootstrap 的 main 方法,實際調用了 Catalina 相應的 load、start 方法。
load 方法會通過 Digester 進行 config/server.xml 的解析,在解析的過程中會根據 xml 中的關系 和配置信息來創建容器,并設置相關的屬性。
接著 Catalina 會調用 StandardServer 的 init 和 start 方法進行容器的初始化和啟動。
按照 xml 的配置關系,server 的子元素是 service,service 的子元素是頂層容器 Engine,每層容器都持有自己的子容器,而這些元素都實現了生命周期管理的各個方法,因此就很容易的完成整個容器的啟動、關閉等生命周期的管理。
StandardServer 完成 init 和 start 方法調用后,會一直監聽來自 8005 端口(可配置)
如果接收 到 shutdown 命令,則會退出循環監聽,執行后續的 stop 和 destroy 方法,完成 Tomcat 容器的關閉。
同時也會調用 JVM 的 Runtime.getRuntime()?.addShutdownHook 方法,在虛擬機意外退出的時候來關閉容器。
所有容器都是繼承自 ContainerBase,基類中封裝了容器中的重復工作,負責啟動容器相關的組件 Loader、Logger、Manager、Cluster、Pipeline,啟動子容器(線程池并發啟動子容器,通過線程池 submit 多個線程,調用后返回 Future 對象,線程內部啟動子容器,接著調用 Future 對象 的 get 方法來等待執行結果)。
List<future> results = new ArrayList<future>();
for (int i = 0; i < children.length; i++) {
results.add(startStopExecutor.submit(new StartChild(children[i])));
}
boolean fail = false;
for (Futureresult :results) {
try {
result.get();
} catch (Exception e) {
log.error(sm.getString("containerBase.threadedStartFailed"), e);
fail = true;
}
}
Web 應用的部署方式
注:catalina.home:安裝目錄;catalina.base:工作目錄;默認值 user.dir
HostConfig 監聽了 StandardHost 容器的事件,在 start 方法中解析上述配置文件:
注:
ContextConfig 解析 context.xml 順序:
ContextConfig 解析 web.xml 順序:
注:
Servlet 生命周期
Servlet 是用 Java 編寫的服務器端程序,其主要功能在于交互式地瀏覽和修改數據,生成動態 Web 內容。
load on startup
當值為 0 或者大于 0 時,表示容器在應用啟動時就加載這個 servlet; 當是一個負數時或者沒有指定時,則指示容器在該 servlet 被選擇時才加載; 正數的值越小,啟動該 servlet 的優先級越高;
single thread model
每次訪問 servlet,新建 servlet 實體對象,但并不能保證線程安全,同時 tomcat 會限制 servlet 的實例數目
最佳實踐:不要使用該模型,servlet 中不要有全局變量
請求處理過程
Pipeline 與 Valve
Pipeline 可以理解為現實中的管道,Valve 為管道中的閥門,Request 和 Response 對象在管道中 經過各個閥門的處理和控制。
每個容器的管道中都有一個必不可少的 basic valve,其他的都是可選的,basic valve 在管道中最 后調用,同時負責調用子容器的第一個 valve。
Valve 中主要的三個方法:setNext、getNext、invoke;valve 之間的關系是單向鏈式結構,本身 invoke 方法中會調用下一個 valve 的 invoke 方法。
各層容器對應的 basic valve 分別是 StandardEngineValve、StandardHostValve、 StandardContextValve、StandardWrapperValve。
JSP引擎
JSP 生命周期
JSP元素
代碼片段:<%>
JSP聲明:<%! ...="">
JSP表達式:<%=>
JSP注釋:<%-->
JSP指令:<%@ directive="" attribute="“value”">
JSP行為:
HTML元素:html/head/body/div/p/…
JSP隱式對象:request、response、out、session、application、config、pageContext、page、Exception
JSP 元素說明
Jsp 解析過程
Connector
Http:HTTP 是超文本傳輸協議,是客戶端瀏覽器或其他程序與 Web 服務器之間的應用層通信協 議
AJP:Apache JServ 協議(AJP)是一種二進制協議,專門代理從 Web 服務器到位于后端的應用 程序服務器的入站請求
阻塞 IO
非阻塞 IO
IO多路復用
阻塞與非阻塞的區別在于進行讀操作和寫操作的系統調用時,如果此時內核態沒有數據可讀或者沒有緩沖空間可寫時,是否阻塞。
IO多路復用的好處在于可同時監聽多個socket的可讀和可寫事件,這樣就能使得應用可以同時監聽多個socket,釋放了應用線程資源。
Tomcat各類Connector對比
Connector的實現模式有三種,分別是BIO、NIO、APR,可以在server.xml中指定。
Apache Portable Runtime是一個高度可移植的庫,它是Apache HTTP Server 2.x的核心。
APR具有許多用途,包括訪問高級IO功能(如sendfile,epoll和OpenSSL),操作系統級功能(隨機數生成,系統狀態等)和本地進程處理(共享內存,NT管道和Unix套接字)
表格中字段含義說明:
NIO處理相關類
Acceptor線程負責接收連接,調用accept方法阻塞接收建立的連接,并對socket進行封裝成PollerEvent,指定注冊的事件為op_read,并放入到EventQueue隊列中,PollerEvent的run方法邏輯的是將Selector注冊到socket的指定事件;
Poller線程從EventQueue獲取PollerEvent,并執行PollerEvent的run方法,調用Selector的select方法,如果有可讀的Socket則創建Http11NioProcessor,放入到線程池中執行
CoyoteAdapter是Connector到Container的適配器,Http11NioProcessor調用其提供的service方法,內部創建Request和Response對象,并調用最頂層容器的Pipeline中的第一個Valve的invoke方法
Mapper主要處理http url 到servlet的映射規則的解析,對外提供map方法
NIO Connector主要參數
Comet
Comet是一種用于web的推送技術,能使服務器實時地將更新的信息傳送到客戶端,而無須客戶端發出請求
在WebSocket出來之前,如果不適用comet,只能通過瀏覽器端輪詢Server來模擬實現服務器端推送。
Comet支持servlet異步處理IO,當連接上數據可讀時觸發事件,并異步寫數據(阻塞)
Tomcat要實現Comet,只需繼承HttpServlet同時,實現CometProcessor接口
Note:
異步Servlet
傳統流程:
異步處理流程:
Servlet 線程將請求轉交給一個異步線程來執行業務處理,線程本身返回至容器,此時 Servlet 還沒有生成響應數據,異步線程處理完業務以后,可以直接生成響應數據(異步線程擁有 ServletRequest 和 ServletResponse 對象的引用)
為什么web應用中支持異步?
推出異步,主要是針對那些比較耗時的請求:比如一次緩慢的數據庫查詢,一次外部REST API調用, 或者是其他一些I/O密集型操作。這種耗時的請求會很快的耗光Servlet容器的線程池,繼而影響可擴展性。
Note:從客戶端的角度來看,request仍然像任何其他的HTTP的request-response交互一樣,只是耗費了更長的時間而已
異步事件監聽
Note :
onError/ onTimeout觸發后,會緊接著回調onComplete
onComplete 執行后,就不可再操作request和response
*請認真填寫需求信息,我們會在24小時內與您取得聯系。