測(cè)引擎:變換、幀內(nèi)預(yù)測(cè)與運(yùn)動(dòng)補(bǔ)償源碼精講)
如何讀懂 rav1d AV1 解碼器三大預(yù)測(cè)引擎變換、幀內(nèi)預(yù)測(cè)與運(yùn)動(dòng)補(bǔ)償源碼精講【免費(fèi)下載鏈接】rav1dAn AV1 decoder in Rust.項(xiàng)目地址: https://gitcode.com/gh_mirrors/ra/rav1drav1d 是一個(gè)高性能 AV1 視頻解碼器核心邏輯已用 Rust 重寫(xiě)同時(shí)保留了關(guān)鍵匯編加速路徑。這篇文章帶你拆解 rav1d 解碼流程中承上啟下的三大預(yù)測(cè)引擎逆變換 itx、幀內(nèi)預(yù)測(cè) ipred 與運(yùn)動(dòng)補(bǔ)償 mc用最少代碼看清它們各自在做什么。 先認(rèn)識(shí) rav1d一個(gè)會(huì)自校驗(yàn)的 AV1 解碼器rav1d 的有趣之處在于它的雙軌架構(gòu)每個(gè)核心函數(shù)都有兩份實(shí)現(xiàn)——純 Rust 的兜底版fallback和針對(duì) x86/SSE、AVX2、AVX512、ARM NEON 等的匯編優(yōu)化版。運(yùn)行時(shí)會(huì)按 CPU 能力自動(dòng)挑選最快的實(shí)現(xiàn)tests/checkasm/目錄還專門負(fù)責(zé)驗(yàn)證匯編版和 Rust 版結(jié)果完全一致。這給了新手一個(gè)巨大福利讀源碼時(shí)只需讀純 Rust 兜底邏輯就能理解算法本意匯編文件如src/x86/itx_sse.asm、src/arm/64/itx.S只負(fù)責(zé)把同一件事做得更快。?? 三大引擎在解碼流程中的位置一個(gè)編碼塊block被解碼出來(lái)之后要變成像素需要經(jīng)過(guò)這樣的流水線量化系數(shù) ── ① 逆變換 itx ── 殘差 預(yù)測(cè)塊 ── ② 幀內(nèi)預(yù)測(cè) ipred 或 ③ 運(yùn)動(dòng)補(bǔ)償 mc ── 預(yù)測(cè)值 殘差 預(yù)測(cè)值 ── 環(huán)路濾波 ── 重建像素幀內(nèi)塊用當(dāng)前幀的上方/左方鄰域預(yù)測(cè)出預(yù)測(cè)塊走src/ipred.rs幀間塊用參考幀按運(yùn)動(dòng)向量插值出預(yù)測(cè)塊走src/mc.rs兩條路匯合后殘差來(lái)自變換域加上去得到重建像素三者共享大量基礎(chǔ)設(shè)施位深抽象src/include/common/bitdepth.h、像素工具src/include/common/intops.h、函數(shù)指針派發(fā)src/wrap_fn_ptr.rs。 引擎一逆變換 itx——把系數(shù)變回像素變換模塊入口是 src/itx.rs一維變換內(nèi)核在 src/itx_1d.rs常量表DCT/ADST 系數(shù)定義在 src/itx.h。AV1 的二維變換被拆成兩次一維變換這是它高效的關(guān)鍵。核心函數(shù)inv_txfm_addsrc/itx.rs 第 41 行起的骨架是這樣的fn inv_txfm_addBD: BitDepth( dst, coeff, eob, w, h, shift, first_1d_fn: Itx1dFn, // 對(duì)每一行做一維變換 second_1d_fn: Itx1dFn, // 對(duì)每一列做一維變換 has_dc_only: bool, bd: BD, )流程分三步走DC-only 快速路徑如果塊里只有一個(gè) DC 系數(shù)平坦區(qū)域跳過(guò)全部矩陣乘法直接把常數(shù)加到每個(gè)像素上dc dc * 181 128 8這樣的定點(diǎn)縮放這是最省算力的路徑行變換對(duì)每行調(diào)用first_1d_fn再右移舍入并截?cái)郼lip防溢出列變換對(duì)每列調(diào)用second_1d_fn最后把結(jié)果加到dst上一維內(nèi)核家族在src/itx_1d.rs中一覽無(wú)余rav1d_inv_dct4_1d_c~rav1d_inv_dct64_1d_cDCT 4/8/16/32/64 點(diǎn)、rav1d_inv_adst4_1d_c系列不對(duì)稱離散正弦變換、rav1d_inv_identity*_1d_cIDTX 恒等變換和rav1d_inv_wht4_1d_c4×4 哈達(dá)瑪。變換類型的組合由常量定義在 src/levels.rs第 129 行起的TxfmType常量含義DCT_DCT行 DCT 列 DCT最常用ADST_DCT/ADST_ADST行/列用 ADST突出角部細(xì)節(jié)IDTX不做變換用于無(wú)損模式WHT_WHT4×4 哈達(dá)瑪無(wú)損專用inv_txfm_add_rustsrc/itx.rs 第 137 行用泛型常量const TYPE: TxfmType在編譯期展開(kāi)出 100 多種 (寬×高×類型) 的具體實(shí)例再由函數(shù)指針表itxfm::Fn在運(yùn)行時(shí)按 CPU 特性替換為sse、avx2、avx512或neon版本——這套編譯期實(shí)例化 運(yùn)行時(shí)派發(fā)是全項(xiàng)目的統(tǒng)一模式。? 引擎二幀內(nèi)預(yù)測(cè) ipred——只靠鄰居猜出像素幀內(nèi)預(yù)測(cè)入口是 src/ipred.rs它實(shí)現(xiàn)了 AV1 的 10 種幀內(nèi)模式源碼里的函數(shù)名和模式一一對(duì)應(yīng)模式源碼函數(shù)直覺(jué)理解DCsplat_dc取上/左邊緣均值鋪滿整塊水平/垂直ipred_h_rust/ipred_v_rust邊緣值逐行/逐列復(fù)制Paethipred_paeth_rust用三鄰居加權(quán)選最可能的邊平滑ipred_smooth_rust及_v/_h變體上/左邊緣漸變相加角度ipred_z1_rust~ipred_z3_rust按角度斜向復(fù)制邊緣濾波/梯度ipred_filter_rust用邊緣梯度做線性外推調(diào)色板pal_pred_rust按索引查調(diào)色板其中角度預(yù)測(cè)最巧妙A(yù)V1 把角度拆成三組Z1/Z2/Z3分別對(duì)應(yīng)不同的步進(jìn)方向45° 附近斜向、接近水平、接近垂直每組內(nèi)部再用查表dav1d_dr_intra_derivative計(jì)算每行的起始偏移。角度模式還帶一個(gè)邊緣重采樣步驟get_filter_strengthsrc/ipred.rs 第 762 行決定用 8 抽頭還是 4 抽頭濾波器filter_edge先平滑邊界upsample_edge再 2 倍插值——保證斜向預(yù)測(cè)線落在整數(shù)像素上。別忘了cfl_pred色度從亮度預(yù)測(cè)它把 Y 平面的預(yù)測(cè)塊按色度子采樣縮小后加權(quán)疊加到 Cb/Cr 預(yù)測(cè)上是提升彩色細(xì)節(jié)的關(guān)鍵。角度預(yù)測(cè)的最終入口angular_ipred通過(guò)wrap_fn_ptr!宏聲明運(yùn)行時(shí)綁定到ipred_z1_sse、ipred_z1_avx512、ipred_z1_neon等匯編實(shí)現(xiàn)見(jiàn)src/x86/ipred*.asm與src/arm/64/ipred*.S。 引擎三運(yùn)動(dòng)補(bǔ)償 mc——從參考幀搬出預(yù)測(cè)塊幀間預(yù)測(cè)入口是 src/mc.rs它要解決的問(wèn)題是運(yùn)動(dòng)向量MV幾乎都是亞像素精度如何從整數(shù)位置的參考幀精確取到任意實(shí)數(shù)位置的像素8 抽頭插值濾波器是主力。put_8tap_rustsrc/mc.rs 第 143 行的工作方式是兩級(jí)流水參考幀 → prep_8tap垂直方向抽頭寫(xiě)入中間平面 → filter_8tap水平方向抽頭輸出最終像素filter_8tap_mid就是一個(gè) 8 項(xiàng)點(diǎn)積Σ f[y] * mid[y][x]濾波系數(shù)表dav1d_mc_subpel_filters定義在src/tables.c。整數(shù)位置則走put_rust的純拷貝快速路徑。此外 mc 模塊還覆蓋了幾類進(jìn)階場(chǎng)景雙線性濾波put_bilin_rustMV 精度超過(guò) 1/8 像素如 1/64時(shí)用雙參考加權(quán)w_avg_rust兩個(gè)參考幀按權(quán)重合并OBMC 重疊塊運(yùn)動(dòng)補(bǔ)償mask_rust/blend_rust/blend_v_rust用預(yù)計(jì)算權(quán)重掩碼dav1d_obmc_masks把兩個(gè)運(yùn)動(dòng)塊平滑融合仿射 warp 運(yùn)動(dòng)warp_affine_8x8_rust按塊內(nèi)每點(diǎn)的局部 MV 逐像素采樣支持旋轉(zhuǎn)/縮放等全局運(yùn)動(dòng)邊緣模擬emu_edge_rust預(yù)測(cè)塊超出畫(huà)面邊界時(shí)用鏡像填充供后續(xù)環(huán)路濾波使用整數(shù)/半像素的prep階段prep_rust會(huì)先把像素左移到中間位深intermediate bits這是 AV1 定點(diǎn)精度規(guī)則的要求所有濾波輸出都統(tǒng)一做rnd2 clip收尾。 性能路徑同一份算法四套機(jī)器碼三大引擎的加速實(shí)現(xiàn)都遵循相同約定C 兜底*_rust函數(shù)、SSE2 基線、AVX2 通用路徑、AVX512 高配路徑、NEON 移動(dòng)路徑。以 itx 為例各架構(gòu)文件一覽x86src/x86/itx_sse.asm、src/x86/itx16_avx512.asm、src/x86/mc_sse.asm、src/x86/ipred_avx2.asmARM64src/arm/64/itx.S、src/arm/64/mc16_sve.SSVE 向量、src/arm/64/ipred.S正確性由tests/checkasm/itx.c、tests/checkasm/ipred.c、tests/checkasm/mc.c保障同一輸入分別喂給 Rust 和匯編實(shí)現(xiàn)逐位比對(duì)。? 三分鐘源碼地圖想動(dòng)手跟讀建議按這個(gè)順序都是純 Rust無(wú)匯編步驟文件看什么1src/itx_1d.rsrav1d_inv_dct4_1d_c最基礎(chǔ)的定點(diǎn)一維變換2src/itx.rsinv_txfm_add行/列兩次一維如何拼成二維3src/ipred.rssplat_dc→ipred_z1_rust從簡(jiǎn)單模式到角度模式4src/mc.rsput_8tap_rust兩級(jí)濾波的亞像素插值5src/levels.rsTxfmType、Filter2d模式與常量全景小結(jié)itx 負(fù)責(zé)系數(shù)→殘差ipred 負(fù)責(zé)幀內(nèi)猜像素mc 負(fù)責(zé)幀間搬像素三者共同決定了重建質(zhì)量而Rust 兜底 匯編加速 checkasm 自校驗(yàn)的架構(gòu)讓你可以放心地只讀 Rust 部分就掌握 AV1 解碼器最核心的一層?!久赓M(fèi)下載鏈接】rav1dAn AV1 decoder in Rust.項(xiàng)目地址: https://gitcode.com/gh_mirrors/ra/rav1d創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考