Vp9Common.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  1. using Ryujinx.Common.Memory;
  2. using Ryujinx.Graphics.Nvdec.Vp9.Common;
  3. using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
  4. using Ryujinx.Graphics.Video;
  5. using System;
  6. namespace Ryujinx.Graphics.Nvdec.Vp9.Types
  7. {
  8. internal struct Vp9Common
  9. {
  10. public MacroBlockD Mb;
  11. public ArrayPtr<TileWorkerData> TileWorkerData;
  12. public int TotalTiles;
  13. public InternalErrorInfo Error;
  14. public VpxColorSpace ColorSpace;
  15. public VpxColorRange ColorRange;
  16. public int Width;
  17. public int Height;
  18. public int RenderWidth;
  19. public int RenderHeight;
  20. public int LastWidth;
  21. public int LastHeight;
  22. public int SubsamplingX;
  23. public int SubsamplingY;
  24. public bool UseHighBitDepth;
  25. public ArrayPtr<MvRef> PrevFrameMvs;
  26. public ArrayPtr<MvRef> CurFrameMvs;
  27. public Ptr<Surface> FrameToShow;
  28. public Ptr<RefCntBuffer> PrevFrame;
  29. public Ptr<RefCntBuffer> CurFrame;
  30. public Array8<int> RefFrameMap; /* maps fb_idx to reference slot */
  31. // Prepare ref_frame_map for the next frame.
  32. // Only used in frame parallel decode.
  33. public Array8<int> NextRefFrameMap;
  34. public Array3<RefBuffer> FrameRefs;
  35. public int NewFbIdx;
  36. public int CurShowFrameFbIdx;
  37. public FrameType LastFrameType;
  38. public FrameType FrameType;
  39. public int ShowFrame;
  40. public int LastShowFrame;
  41. public int ShowExistingFrame;
  42. // Flag signaling that the frame is encoded using only Intra modes.
  43. public bool IntraOnly;
  44. public bool LastIntraOnly;
  45. public bool AllowHighPrecisionMv;
  46. public int ResetFrameContext;
  47. // MBs, MbRows/Cols is in 16-pixel units; MiRows/Cols is in
  48. // ModeInfo (8-pixel) units.
  49. public int MBs;
  50. public int MbRows, MiRows;
  51. public int MbCols, MiCols;
  52. public int MiStride;
  53. /* Profile settings */
  54. public TxMode TxMode;
  55. public int BaseQindex;
  56. public int YDcDeltaQ;
  57. public int UvDcDeltaQ;
  58. public int UvAcDeltaQ;
  59. public Array8<Array2<short>> YDequant;
  60. public Array8<Array2<short>> UvDequant;
  61. /* We allocate a ModeInfo struct for each macroblock, together with
  62. an extra row on top and column on the left to simplify prediction. */
  63. public int MiAllocSize;
  64. public ArrayPtr<ModeInfo> Mip; /* Base of allocated array */
  65. public ArrayPtr<ModeInfo> Mi; /* Corresponds to upper left visible macroblock */
  66. // prev_mip and prev_mi will only be allocated in VP9 encoder.
  67. public Ptr<ModeInfo> PrevMip; /* MODE_INFO array 'mip' from last decoded frame */
  68. public Ptr<ModeInfo> PrevMi; /* 'mi' from last frame (points into prev_mip) */
  69. public ArrayPtr<Ptr<ModeInfo>> MiGridBase;
  70. public ArrayPtr<Ptr<ModeInfo>> MiGridVisible;
  71. // Whether to use previous frame's motion vectors for prediction.
  72. public bool UsePrevFrameMvs;
  73. // Persistent mb segment id map used in prediction.
  74. public int SegMapIdx;
  75. public int PrevSegMapIdx;
  76. public Array2<ArrayPtr<byte>> SegMapArray;
  77. public ArrayPtr<byte> LastFrameSegMap;
  78. public ArrayPtr<byte> CurrentFrameSegMap;
  79. public byte InterpFilter;
  80. public LoopFilterInfoN LfInfo;
  81. public int RefreshFrameContext; /* Two state 0 = NO, 1 = YES */
  82. public Array4<sbyte> RefFrameSignBias; /* Two state 0, 1 */
  83. public LoopFilter Lf;
  84. public Segmentation Seg;
  85. // Context probabilities for reference frame prediction
  86. public sbyte CompFixedRef;
  87. public Array2<sbyte> CompVarRef;
  88. public ReferenceMode ReferenceMode;
  89. public Ptr<Vp9EntropyProbs> Fc;
  90. public ArrayPtr<Vp9EntropyProbs> FrameContexts; // FRAME_CONTEXTS
  91. public uint FrameContextIdx; /* Context to use/update */
  92. public Ptr<Vp9BackwardUpdates> Counts;
  93. public uint CurrentVideoFrame;
  94. public BitstreamProfile Profile;
  95. public BitDepth BitDepth;
  96. public BitDepth DequantBitDepth; // bit_depth of current dequantizer
  97. public int ErrorResilientMode;
  98. public int FrameParallelDecodingMode;
  99. public int Log2TileCols, Log2TileRows;
  100. public int ByteAlignment;
  101. public int SkipLoopFilter;
  102. public Ptr<BufferPool> BufferPool;
  103. public ArrayPtr<sbyte> AboveSegContext;
  104. public ArrayPtr<sbyte> AboveContext;
  105. public bool FrameIsIntraOnly()
  106. {
  107. return FrameType == FrameType.KeyFrame || IntraOnly;
  108. }
  109. public bool CompoundReferenceAllowed()
  110. {
  111. for (int i = 1; i < Constants.RefsPerFrame; ++i)
  112. {
  113. if (RefFrameSignBias[i + 1] != RefFrameSignBias[1])
  114. {
  115. return true;
  116. }
  117. }
  118. return false;
  119. }
  120. public ref Surface GetFrameNewBuffer()
  121. {
  122. return ref BufferPool.Value.FrameBufs[NewFbIdx].Buf;
  123. }
  124. public int GetFreeFb()
  125. {
  126. ref Array12<RefCntBuffer> frameBufs = ref BufferPool.Value.FrameBufs;
  127. int i;
  128. for (i = 0; i < Constants.FrameBuffers; ++i)
  129. {
  130. if (frameBufs[i].RefCount == 0)
  131. {
  132. break;
  133. }
  134. }
  135. if (i != Constants.FrameBuffers)
  136. {
  137. frameBufs[i].RefCount = 1;
  138. }
  139. else
  140. {
  141. // Reset i to be INVALID_IDX to indicate no free buffer found.
  142. i = RefBuffer.InvalidIdx;
  143. }
  144. return i;
  145. }
  146. public void SwapCurrentAndLastSegMap()
  147. {
  148. // Swap indices.
  149. (SegMapIdx, PrevSegMapIdx) = (PrevSegMapIdx, SegMapIdx);
  150. CurrentFrameSegMap = SegMapArray[SegMapIdx];
  151. LastFrameSegMap = SegMapArray[PrevSegMapIdx];
  152. }
  153. private static int CalcMiSize(int len)
  154. {
  155. // Len is in mi units.
  156. return len + Constants.MiBlockSize;
  157. }
  158. public void SetMbMi(int width, int height)
  159. {
  160. int alignedWidth = BitUtils.AlignPowerOfTwo(width, Constants.MiSizeLog2);
  161. int alignedHeight = BitUtils.AlignPowerOfTwo(height, Constants.MiSizeLog2);
  162. MiCols = alignedWidth >> Constants.MiSizeLog2;
  163. MiRows = alignedHeight >> Constants.MiSizeLog2;
  164. MiStride = CalcMiSize(MiCols);
  165. MbCols = (MiCols + 1) >> 1;
  166. MbRows = (MiRows + 1) >> 1;
  167. MBs = MbRows * MbCols;
  168. }
  169. public void AllocTileWorkerData(MemoryAllocator allocator, int tileCols, int tileRows, int maxThreads)
  170. {
  171. TileWorkerData =
  172. allocator.Allocate<TileWorkerData>((tileCols * tileRows) + (maxThreads > 1 ? maxThreads : 0));
  173. }
  174. public void FreeTileWorkerData(MemoryAllocator allocator)
  175. {
  176. allocator.Free(TileWorkerData);
  177. }
  178. private void AllocSegMap(MemoryAllocator allocator, int segMapSize)
  179. {
  180. for (int i = 0; i < Constants.NumPingPongBuffers; ++i)
  181. {
  182. SegMapArray[i] = allocator.Allocate<byte>(segMapSize);
  183. }
  184. // Init the index.
  185. SegMapIdx = 0;
  186. PrevSegMapIdx = 1;
  187. CurrentFrameSegMap = SegMapArray[SegMapIdx];
  188. LastFrameSegMap = SegMapArray[PrevSegMapIdx];
  189. }
  190. private void FreeSegMap(MemoryAllocator allocator)
  191. {
  192. for (int i = 0; i < Constants.NumPingPongBuffers; ++i)
  193. {
  194. allocator.Free(SegMapArray[i]);
  195. SegMapArray[i] = ArrayPtr<byte>.Null;
  196. }
  197. CurrentFrameSegMap = ArrayPtr<byte>.Null;
  198. LastFrameSegMap = ArrayPtr<byte>.Null;
  199. }
  200. private void DecAllocMi(MemoryAllocator allocator, int miSize)
  201. {
  202. Mip = allocator.Allocate<ModeInfo>(miSize);
  203. MiGridBase = allocator.Allocate<Ptr<ModeInfo>>(miSize);
  204. }
  205. private void DecFreeMi(MemoryAllocator allocator)
  206. {
  207. allocator.Free(Mip);
  208. Mip = ArrayPtr<ModeInfo>.Null;
  209. allocator.Free(MiGridBase);
  210. MiGridBase = ArrayPtr<Ptr<ModeInfo>>.Null;
  211. }
  212. public void FreeContextBuffers(MemoryAllocator allocator)
  213. {
  214. DecFreeMi(allocator);
  215. FreeSegMap(allocator);
  216. allocator.Free(AboveContext);
  217. AboveContext = ArrayPtr<sbyte>.Null;
  218. allocator.Free(AboveSegContext);
  219. AboveSegContext = ArrayPtr<sbyte>.Null;
  220. allocator.Free(Lf.Lfm);
  221. Lf.Lfm = ArrayPtr<LoopFilterMask>.Null;
  222. allocator.Free(CurFrameMvs);
  223. CurFrameMvs = ArrayPtr<MvRef>.Null;
  224. if (UsePrevFrameMvs)
  225. {
  226. allocator.Free(PrevFrameMvs);
  227. PrevFrameMvs = ArrayPtr<MvRef>.Null;
  228. }
  229. }
  230. private void AllocLoopFilter(MemoryAllocator allocator)
  231. {
  232. // Each lfm holds bit masks for all the 8x8 blocks in a 64x64 region. The
  233. // stride and rows are rounded up / truncated to a multiple of 8.
  234. Lf.LfmStride = (MiCols + (Constants.MiBlockSize - 1)) >> 3;
  235. Lf.Lfm = allocator.Allocate<LoopFilterMask>(((MiRows + (Constants.MiBlockSize - 1)) >> 3) * Lf.LfmStride);
  236. }
  237. public bool AllocContextBuffers(MemoryAllocator allocator, int width, int height)
  238. {
  239. SetMbMi(width, height);
  240. int newMiSize = MiStride * CalcMiSize(MiRows);
  241. if (newMiSize != 0)
  242. {
  243. DecAllocMi(allocator, newMiSize);
  244. }
  245. if (MiRows * MiCols != 0)
  246. {
  247. // Create the segmentation map structure and set to 0.
  248. AllocSegMap(allocator, MiRows * MiCols);
  249. }
  250. if (MiCols != 0)
  251. {
  252. AboveContext = allocator.Allocate<sbyte>(2 * TileInfo.MiColsAlignedToSb(MiCols) * Constants.MaxMbPlane);
  253. AboveSegContext = allocator.Allocate<sbyte>(TileInfo.MiColsAlignedToSb(MiCols));
  254. }
  255. AllocLoopFilter(allocator);
  256. CurFrameMvs = allocator.Allocate<MvRef>(MiRows * MiCols);
  257. // Using the same size as the current frame is fine here,
  258. // as this is never true when we have a resolution change.
  259. if (UsePrevFrameMvs)
  260. {
  261. PrevFrameMvs = allocator.Allocate<MvRef>(MiRows * MiCols);
  262. }
  263. return false;
  264. }
  265. private unsafe void DecSetupMi()
  266. {
  267. Mi = Mip.Slice(MiStride + 1);
  268. MiGridVisible = MiGridBase.Slice(MiStride + 1);
  269. MemoryUtil.Fill(MiGridBase.ToPointer(), Ptr<ModeInfo>.Null, MiStride * (MiRows + 1));
  270. }
  271. public unsafe void InitContextBuffers()
  272. {
  273. DecSetupMi();
  274. if (!LastFrameSegMap.IsNull)
  275. {
  276. MemoryUtil.Fill(LastFrameSegMap.ToPointer(), (byte)0, MiRows * MiCols);
  277. }
  278. }
  279. private void SetPartitionProbs(ref MacroBlockD xd)
  280. {
  281. xd.PartitionProbs = FrameIsIntraOnly()
  282. ? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16)
  283. : new ArrayPtr<Array3<byte>>(ref Fc.Value.PartitionProb[0], 16);
  284. }
  285. internal void InitMacroBlockD(ref MacroBlockD xd, ArrayPtr<int> dqcoeff)
  286. {
  287. for (int i = 0; i < Constants.MaxMbPlane; ++i)
  288. {
  289. xd.Plane[i].DqCoeff = dqcoeff;
  290. xd.AboveContext[i] = AboveContext.Slice(i * 2 * TileInfo.MiColsAlignedToSb(MiCols));
  291. if (i == 0)
  292. {
  293. MemoryUtil.Copy(ref xd.Plane[i].SegDequant, ref YDequant);
  294. }
  295. else
  296. {
  297. MemoryUtil.Copy(ref xd.Plane[i].SegDequant, ref UvDequant);
  298. }
  299. xd.Fc = new Ptr<Vp9EntropyProbs>(ref Fc.Value);
  300. }
  301. xd.AboveSegContext = AboveSegContext;
  302. xd.MiStride = MiStride;
  303. xd.ErrorInfo = new Ptr<InternalErrorInfo>(ref Error);
  304. SetPartitionProbs(ref xd);
  305. }
  306. public void SetupSegmentationDequant()
  307. {
  308. // Build y/uv dequant values based on segmentation.
  309. if (Seg.Enabled)
  310. {
  311. for (int i = 0; i < Constants.MaxSegments; ++i)
  312. {
  313. int qindex = Seg.GetQIndex(i, BaseQindex);
  314. YDequant[i][0] = QuantCommon.DcQuant(qindex, YDcDeltaQ, BitDepth);
  315. YDequant[i][1] = QuantCommon.AcQuant(qindex, 0, BitDepth);
  316. UvDequant[i][0] = QuantCommon.DcQuant(qindex, UvDcDeltaQ, BitDepth);
  317. UvDequant[i][1] = QuantCommon.AcQuant(qindex, UvAcDeltaQ, BitDepth);
  318. }
  319. }
  320. else
  321. {
  322. int qindex = BaseQindex;
  323. // When segmentation is disabled, only the first value is used. The
  324. // remaining are don't cares.
  325. YDequant[0][0] = QuantCommon.DcQuant(qindex, YDcDeltaQ, BitDepth);
  326. YDequant[0][1] = QuantCommon.AcQuant(qindex, 0, BitDepth);
  327. UvDequant[0][0] = QuantCommon.DcQuant(qindex, UvDcDeltaQ, BitDepth);
  328. UvDequant[0][1] = QuantCommon.AcQuant(qindex, UvAcDeltaQ, BitDepth);
  329. }
  330. }
  331. public void SetupScaleFactors()
  332. {
  333. for (int i = 0; i < Constants.RefsPerFrame; ++i)
  334. {
  335. ref RefBuffer refBuf = ref FrameRefs[i];
  336. refBuf.Sf.SetupScaleFactorsForFrame(refBuf.Buf.Width, refBuf.Buf.Height, Width, Height);
  337. }
  338. }
  339. public void ReadFrameReferenceModeProbs(ref Reader r)
  340. {
  341. ref Vp9EntropyProbs fc = ref Fc.Value;
  342. if (ReferenceMode == ReferenceMode.Select)
  343. {
  344. for (int i = 0; i < Constants.CompInterContexts; ++i)
  345. {
  346. r.DiffUpdateProb(ref fc.CompInterProb[i]);
  347. }
  348. }
  349. if (ReferenceMode != ReferenceMode.Compound)
  350. {
  351. for (int i = 0; i < Constants.RefContexts; ++i)
  352. {
  353. r.DiffUpdateProb(ref fc.SingleRefProb[i][0]);
  354. r.DiffUpdateProb(ref fc.SingleRefProb[i][1]);
  355. }
  356. }
  357. if (ReferenceMode != ReferenceMode.Single)
  358. {
  359. for (int i = 0; i < Constants.RefContexts; ++i)
  360. {
  361. r.DiffUpdateProb(ref fc.CompRefProb[i]);
  362. }
  363. }
  364. }
  365. public ReferenceMode ReadFrameReferenceMode(ref Reader r)
  366. {
  367. if (CompoundReferenceAllowed())
  368. {
  369. return r.ReadBit() != 0
  370. ? r.ReadBit() != 0 ? ReferenceMode.Select : ReferenceMode.Compound
  371. : ReferenceMode.Single;
  372. }
  373. return ReferenceMode.Single;
  374. }
  375. public void SetupCompoundReferenceMode()
  376. {
  377. if (RefFrameSignBias[Constants.LastFrame] == RefFrameSignBias[Constants.GoldenFrame])
  378. {
  379. CompFixedRef = Constants.AltRefFrame;
  380. CompVarRef[0] = Constants.LastFrame;
  381. CompVarRef[1] = Constants.GoldenFrame;
  382. }
  383. else if (RefFrameSignBias[Constants.LastFrame] == RefFrameSignBias[Constants.AltRefFrame])
  384. {
  385. CompFixedRef = Constants.GoldenFrame;
  386. CompVarRef[0] = Constants.LastFrame;
  387. CompVarRef[1] = Constants.AltRefFrame;
  388. }
  389. else
  390. {
  391. CompFixedRef = Constants.LastFrame;
  392. CompVarRef[0] = Constants.GoldenFrame;
  393. CompVarRef[1] = Constants.AltRefFrame;
  394. }
  395. }
  396. public void InitMvProbs()
  397. {
  398. Fc.Value.Joints[0] = 32;
  399. Fc.Value.Joints[1] = 64;
  400. Fc.Value.Joints[2] = 96;
  401. Fc.Value.Sign[0] = 128;
  402. Fc.Value.Classes[0][0] = 224;
  403. Fc.Value.Classes[0][1] = 144;
  404. Fc.Value.Classes[0][2] = 192;
  405. Fc.Value.Classes[0][3] = 168;
  406. Fc.Value.Classes[0][4] = 192;
  407. Fc.Value.Classes[0][5] = 176;
  408. Fc.Value.Classes[0][6] = 192;
  409. Fc.Value.Classes[0][7] = 198;
  410. Fc.Value.Classes[0][8] = 198;
  411. Fc.Value.Classes[0][9] = 245;
  412. Fc.Value.Class0[0][0] = 216;
  413. Fc.Value.Bits[0][0] = 136;
  414. Fc.Value.Bits[0][1] = 140;
  415. Fc.Value.Bits[0][2] = 148;
  416. Fc.Value.Bits[0][3] = 160;
  417. Fc.Value.Bits[0][4] = 176;
  418. Fc.Value.Bits[0][5] = 192;
  419. Fc.Value.Bits[0][6] = 224;
  420. Fc.Value.Bits[0][7] = 234;
  421. Fc.Value.Bits[0][8] = 234;
  422. Fc.Value.Bits[0][9] = 240;
  423. Fc.Value.Class0Fp[0][0][0] = 128;
  424. Fc.Value.Class0Fp[0][0][1] = 128;
  425. Fc.Value.Class0Fp[0][0][2] = 64;
  426. Fc.Value.Class0Fp[0][1][0] = 96;
  427. Fc.Value.Class0Fp[0][1][1] = 112;
  428. Fc.Value.Class0Fp[0][1][2] = 64;
  429. Fc.Value.Fp[0][0] = 64;
  430. Fc.Value.Fp[0][1] = 96;
  431. Fc.Value.Fp[0][2] = 64;
  432. Fc.Value.Class0Hp[0] = 160;
  433. Fc.Value.Hp[0] = 128;
  434. Fc.Value.Sign[1] = 128;
  435. Fc.Value.Classes[1][0] = 216;
  436. Fc.Value.Classes[1][1] = 128;
  437. Fc.Value.Classes[1][2] = 176;
  438. Fc.Value.Classes[1][3] = 160;
  439. Fc.Value.Classes[1][4] = 176;
  440. Fc.Value.Classes[1][5] = 176;
  441. Fc.Value.Classes[1][6] = 192;
  442. Fc.Value.Classes[1][7] = 198;
  443. Fc.Value.Classes[1][8] = 198;
  444. Fc.Value.Classes[1][9] = 208;
  445. Fc.Value.Class0[1][0] = 208;
  446. Fc.Value.Bits[1][0] = 136;
  447. Fc.Value.Bits[1][1] = 140;
  448. Fc.Value.Bits[1][2] = 148;
  449. Fc.Value.Bits[1][3] = 160;
  450. Fc.Value.Bits[1][4] = 176;
  451. Fc.Value.Bits[1][5] = 192;
  452. Fc.Value.Bits[1][6] = 224;
  453. Fc.Value.Bits[1][7] = 234;
  454. Fc.Value.Bits[1][8] = 234;
  455. Fc.Value.Bits[1][9] = 240;
  456. Fc.Value.Class0Fp[1][0][0] = 128;
  457. Fc.Value.Class0Fp[1][0][1] = 128;
  458. Fc.Value.Class0Fp[1][0][2] = 64;
  459. Fc.Value.Class0Fp[1][1][0] = 96;
  460. Fc.Value.Class0Fp[1][1][1] = 112;
  461. Fc.Value.Class0Fp[1][1][2] = 64;
  462. Fc.Value.Fp[1][0] = 64;
  463. Fc.Value.Fp[1][1] = 96;
  464. Fc.Value.Fp[1][2] = 64;
  465. Fc.Value.Class0Hp[1] = 160;
  466. Fc.Value.Hp[1] = 128;
  467. }
  468. public void AdaptMvProbs(bool allowHp)
  469. {
  470. ref Vp9EntropyProbs fc = ref Fc.Value;
  471. ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
  472. ref Vp9BackwardUpdates counts = ref Counts.Value;
  473. Prob.VpxTreeMergeProbs(
  474. EntropyMv.JointTree,
  475. preFc.Joints.AsSpan(),
  476. counts.Joints.AsSpan(),
  477. fc.Joints.AsSpan());
  478. for (int i = 0; i < 2; ++i)
  479. {
  480. fc.Sign[i] = Prob.ModeMvMergeProbs(preFc.Sign[i], ref counts.Sign[i]);
  481. Prob.VpxTreeMergeProbs(
  482. EntropyMv.ClassTree,
  483. preFc.Classes[i].AsSpan(),
  484. counts.Classes[i].AsSpan(),
  485. fc.Classes[i].AsSpan());
  486. Prob.VpxTreeMergeProbs(
  487. EntropyMv.Class0Tree,
  488. preFc.Class0[i].AsSpan(),
  489. counts.Class0[i].AsSpan(),
  490. fc.Class0[i].AsSpan());
  491. for (int j = 0; j < EntropyMv.OffsetBits; ++j)
  492. {
  493. fc.Bits[i][j] = Prob.ModeMvMergeProbs(preFc.Bits[i][j], ref counts.Bits[i][j]);
  494. }
  495. for (int j = 0; j < EntropyMv.Class0Size; ++j)
  496. {
  497. Prob.VpxTreeMergeProbs(
  498. EntropyMv.FpTree,
  499. preFc.Class0Fp[i][j].AsSpan(),
  500. counts.Class0Fp[i][j].AsSpan(),
  501. fc.Class0Fp[i][j].AsSpan());
  502. }
  503. Prob.VpxTreeMergeProbs(EntropyMv.FpTree, preFc.Fp[i].AsSpan(), counts.Fp[i].AsSpan(),
  504. fc.Fp[i].AsSpan());
  505. if (allowHp)
  506. {
  507. fc.Class0Hp[i] = Prob.ModeMvMergeProbs(preFc.Class0Hp[i], ref counts.Class0Hp[i]);
  508. fc.Hp[i] = Prob.ModeMvMergeProbs(preFc.Hp[i], ref counts.Hp[i]);
  509. }
  510. }
  511. }
  512. public void ResizeContextBuffers(MemoryAllocator allocator, int width, int height)
  513. {
  514. if (Width != width || Height != height)
  515. {
  516. int newMiRows = BitUtils.AlignPowerOfTwo(height, Constants.MiSizeLog2) >> Constants.MiSizeLog2;
  517. int newMiCols = BitUtils.AlignPowerOfTwo(width, Constants.MiSizeLog2) >> Constants.MiSizeLog2;
  518. // Allocations in AllocContextBuffers() depend on individual
  519. // dimensions as well as the overall size.
  520. if (newMiCols > MiCols || newMiRows > MiRows)
  521. {
  522. if (AllocContextBuffers(allocator, width, height))
  523. {
  524. // The Mi* values have been cleared and any existing context
  525. // buffers have been freed. Clear Width and Height to be
  526. // consistent and to force a realloc next time.
  527. Width = 0;
  528. Height = 0;
  529. Error.InternalError(CodecErr.MemError, "Failed to allocate context buffers");
  530. }
  531. }
  532. else
  533. {
  534. SetMbMi(width, height);
  535. }
  536. InitContextBuffers();
  537. Width = width;
  538. Height = height;
  539. }
  540. if (CurFrameMvs.IsNull ||
  541. MiRows > CurFrame.Value.MiRows ||
  542. MiCols > CurFrame.Value.MiCols)
  543. {
  544. ResizeMvBuffer(allocator);
  545. }
  546. }
  547. public void CheckMemError<T>(ref ArrayPtr<T> lval, ArrayPtr<T> expr)
  548. where T : unmanaged
  549. {
  550. lval = expr;
  551. if (lval.IsNull)
  552. {
  553. Error.InternalError(CodecErr.MemError, "Failed to allocate");
  554. }
  555. }
  556. private void ResizeMvBuffer(MemoryAllocator allocator)
  557. {
  558. allocator.Free(CurFrameMvs);
  559. CurFrame.Value.MiRows = MiRows;
  560. CurFrame.Value.MiCols = MiCols;
  561. CheckMemError(ref CurFrameMvs, allocator.Allocate<MvRef>(MiRows * MiCols));
  562. }
  563. public void CheckMemError<T>(ref Ptr<T> lval, Ptr<T> expr) where T : unmanaged
  564. {
  565. lval = expr;
  566. if (lval.IsNull)
  567. {
  568. Error.InternalError(CodecErr.MemError, "Failed to allocate");
  569. }
  570. }
  571. public void SetupTileInfo(ref ReadBitBuffer rb)
  572. {
  573. int minLog2TileCols = 0, maxLog2TileCols = 0, maxOnes;
  574. TileInfo.GetTileNBits(MiCols, out minLog2TileCols, out maxLog2TileCols);
  575. // columns
  576. maxOnes = maxLog2TileCols - minLog2TileCols;
  577. Log2TileCols = minLog2TileCols;
  578. while (maxOnes-- != 0 && rb.ReadBit() != 0)
  579. {
  580. Log2TileCols++;
  581. }
  582. if (Log2TileCols > 6)
  583. {
  584. Error.InternalError(CodecErr.CorruptFrame, "Invalid number of tile columns");
  585. }
  586. // rows
  587. Log2TileRows = rb.ReadBit();
  588. if (Log2TileRows != 0)
  589. {
  590. Log2TileRows += rb.ReadBit();
  591. }
  592. }
  593. public void ReadBitdepthColorspaceSampling(ref ReadBitBuffer rb)
  594. {
  595. if (Profile >= BitstreamProfile.Profile2)
  596. {
  597. BitDepth = rb.ReadBit() != 0 ? BitDepth.Bits12 : BitDepth.Bits10;
  598. UseHighBitDepth = true;
  599. }
  600. else
  601. {
  602. BitDepth = BitDepth.Bits8;
  603. UseHighBitDepth = false;
  604. }
  605. ColorSpace = (VpxColorSpace)rb.ReadLiteral(3);
  606. if (ColorSpace != VpxColorSpace.Srgb)
  607. {
  608. ColorRange = (VpxColorRange)rb.ReadBit();
  609. if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3)
  610. {
  611. SubsamplingX = rb.ReadBit();
  612. SubsamplingY = rb.ReadBit();
  613. if (SubsamplingX == 1 && SubsamplingY == 1)
  614. {
  615. Error.InternalError(CodecErr.UnsupBitstream,
  616. "4:2:0 color not supported in profile 1 or 3");
  617. }
  618. if (rb.ReadBit() != 0)
  619. {
  620. Error.InternalError(CodecErr.UnsupBitstream, "Reserved bit set");
  621. }
  622. }
  623. else
  624. {
  625. SubsamplingY = SubsamplingX = 1;
  626. }
  627. }
  628. else
  629. {
  630. ColorRange = VpxColorRange.Full;
  631. if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3)
  632. {
  633. // Note if colorspace is SRGB then 4:4:4 chroma sampling is assumed.
  634. // 4:2:2 or 4:4:0 chroma sampling is not allowed.
  635. SubsamplingY = SubsamplingX = 0;
  636. if (rb.ReadBit() != 0)
  637. {
  638. Error.InternalError(CodecErr.UnsupBitstream, "Reserved bit set");
  639. }
  640. }
  641. else
  642. {
  643. Error.InternalError(CodecErr.UnsupBitstream, "4:4:4 color not supported in profile 0 or 2");
  644. }
  645. }
  646. }
  647. public void AdaptModeProbs()
  648. {
  649. ref Vp9EntropyProbs fc = ref Fc.Value;
  650. ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
  651. ref Vp9BackwardUpdates counts = ref Counts.Value;
  652. for (int i = 0; i < Constants.IntraInterContexts; i++)
  653. {
  654. fc.IntraInterProb[i] = Prob.ModeMvMergeProbs(preFc.IntraInterProb[i], ref counts.IntraInter[i]);
  655. }
  656. for (int i = 0; i < Constants.CompInterContexts; i++)
  657. {
  658. fc.CompInterProb[i] = Prob.ModeMvMergeProbs(preFc.CompInterProb[i], ref counts.CompInter[i]);
  659. }
  660. for (int i = 0; i < Constants.RefContexts; i++)
  661. {
  662. fc.CompRefProb[i] = Prob.ModeMvMergeProbs(preFc.CompRefProb[i], ref counts.CompRef[i]);
  663. }
  664. for (int i = 0; i < Constants.RefContexts; i++)
  665. {
  666. for (int j = 0; j < 2; j++)
  667. {
  668. fc.SingleRefProb[i][j] =
  669. Prob.ModeMvMergeProbs(preFc.SingleRefProb[i][j], ref counts.SingleRef[i][j]);
  670. }
  671. }
  672. for (int i = 0; i < Constants.InterModeContexts; i++)
  673. {
  674. Prob.VpxTreeMergeProbs(
  675. EntropyMode.InterModeTree,
  676. preFc.InterModeProb[i].AsSpan(),
  677. counts.InterMode[i].AsSpan(),
  678. fc.InterModeProb[i].AsSpan());
  679. }
  680. for (int i = 0; i < EntropyMode.BlockSizeGroups; i++)
  681. {
  682. Prob.VpxTreeMergeProbs(
  683. EntropyMode.IntraModeTree,
  684. preFc.YModeProb[i].AsSpan(),
  685. counts.YMode[i].AsSpan(),
  686. fc.YModeProb[i].AsSpan());
  687. }
  688. for (int i = 0; i < Constants.IntraModes; ++i)
  689. {
  690. Prob.VpxTreeMergeProbs(
  691. EntropyMode.IntraModeTree,
  692. preFc.UvModeProb[i].AsSpan(),
  693. counts.UvMode[i].AsSpan(),
  694. fc.UvModeProb[i].AsSpan());
  695. }
  696. for (int i = 0; i < Constants.PartitionContexts; i++)
  697. {
  698. Prob.VpxTreeMergeProbs(
  699. EntropyMode.PartitionTree,
  700. preFc.PartitionProb[i].AsSpan(),
  701. counts.Partition[i].AsSpan(),
  702. fc.PartitionProb[i].AsSpan());
  703. }
  704. if (InterpFilter == Constants.Switchable)
  705. {
  706. for (int i = 0; i < Constants.SwitchableFilterContexts; i++)
  707. {
  708. Prob.VpxTreeMergeProbs(
  709. EntropyMode.SwitchableInterpTree,
  710. preFc.SwitchableInterpProb[i].AsSpan(),
  711. counts.SwitchableInterp[i].AsSpan(),
  712. fc.SwitchableInterpProb[i].AsSpan());
  713. }
  714. }
  715. if (TxMode == TxMode.TxModeSelect)
  716. {
  717. Array1<Array2<uint>> branchCt8x8P = new();
  718. Array2<Array2<uint>> branchCt16x16P = new();
  719. Array3<Array2<uint>> branchCt32x32P = new();
  720. for (int i = 0; i < EntropyMode.TxSizeContexts; ++i)
  721. {
  722. EntropyMode.TxCountsToBranchCounts8x8(counts.Tx8x8[i].AsSpan(), ref branchCt8x8P);
  723. for (int j = 0; j < (int)TxSize.TxSizes - 3; ++j)
  724. {
  725. fc.Tx8x8Prob[i][j] = Prob.ModeMvMergeProbs(preFc.Tx8x8Prob[i][j], ref branchCt8x8P[j]);
  726. }
  727. EntropyMode.TxCountsToBranchCounts16x16(counts.Tx16x16[i].AsSpan(), ref branchCt16x16P);
  728. for (int j = 0; j < (int)TxSize.TxSizes - 2; ++j)
  729. {
  730. fc.Tx16x16Prob[i][j] =
  731. Prob.ModeMvMergeProbs(preFc.Tx16x16Prob[i][j], ref branchCt16x16P[j]);
  732. }
  733. EntropyMode.TxCountsToBranchCounts32x32(counts.Tx32x32[i].AsSpan(), ref branchCt32x32P);
  734. for (int j = 0; j < (int)TxSize.TxSizes - 1; ++j)
  735. {
  736. fc.Tx32x32Prob[i][j] =
  737. Prob.ModeMvMergeProbs(preFc.Tx32x32Prob[i][j], ref branchCt32x32P[j]);
  738. }
  739. }
  740. }
  741. for (int i = 0; i < Constants.SkipContexts; ++i)
  742. {
  743. fc.SkipProb[i] = Prob.ModeMvMergeProbs(preFc.SkipProb[i], ref counts.Skip[i]);
  744. }
  745. }
  746. public void AdaptCoefProbs()
  747. {
  748. byte t;
  749. uint countSat, updateFactor;
  750. if (FrameIsIntraOnly())
  751. {
  752. updateFactor = Entropy.CoefMaxUpdateFactorKey;
  753. countSat = Entropy.CoefCountSatKey;
  754. }
  755. else if (LastFrameType == FrameType.KeyFrame)
  756. {
  757. updateFactor = Entropy.CoefMaxUpdateFactorAfterKey; /* adapt quickly */
  758. countSat = Entropy.CoefCountSatAfterKey;
  759. }
  760. else
  761. {
  762. updateFactor = Entropy.CoefMaxUpdateFactor;
  763. countSat = Entropy.CoefCountSat;
  764. }
  765. for (t = (int)TxSize.Tx4x4; t <= (int)TxSize.Tx32x32; t++)
  766. {
  767. AdaptCoefProbs(t, countSat, updateFactor);
  768. }
  769. }
  770. public void SetMvs(ReadOnlySpan<Vp9MvRef> mvs)
  771. {
  772. if (mvs.Length > PrevFrameMvs.Length)
  773. {
  774. throw new ArgumentException(
  775. $"Size mismatch, expected: {PrevFrameMvs.Length}, but got: {mvs.Length}.");
  776. }
  777. for (int i = 0; i < mvs.Length; i++)
  778. {
  779. ref MvRef mv = ref PrevFrameMvs[i];
  780. mv.Mv[0].Row = mvs[i].Mvs[0].Row;
  781. mv.Mv[0].Col = mvs[i].Mvs[0].Col;
  782. mv.Mv[1].Row = mvs[i].Mvs[1].Row;
  783. mv.Mv[1].Col = mvs[i].Mvs[1].Col;
  784. mv.RefFrame[0] = (sbyte)mvs[i].RefFrames[0];
  785. mv.RefFrame[1] = (sbyte)mvs[i].RefFrames[1];
  786. }
  787. }
  788. public void GetMvs(Span<Vp9MvRef> mvs)
  789. {
  790. if (mvs.Length > CurFrameMvs.Length)
  791. {
  792. throw new ArgumentException(
  793. $"Size mismatch, expected: {CurFrameMvs.Length}, but got: {mvs.Length}.");
  794. }
  795. for (int i = 0; i < mvs.Length; i++)
  796. {
  797. ref MvRef mv = ref CurFrameMvs[i];
  798. mvs[i].Mvs[0].Row = mv.Mv[0].Row;
  799. mvs[i].Mvs[0].Col = mv.Mv[0].Col;
  800. mvs[i].Mvs[1].Row = mv.Mv[1].Row;
  801. mvs[i].Mvs[1].Col = mv.Mv[1].Col;
  802. mvs[i].RefFrames[0] = mv.RefFrame[0];
  803. mvs[i].RefFrames[1] = mv.RefFrame[1];
  804. }
  805. }
  806. private void AdaptCoefProbs(byte txSize, uint countSat, uint updateFactor)
  807. {
  808. ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
  809. ref Array2<Array2<Array6<Array6<Array3<byte>>>>> probs = ref Fc.Value.CoefProbs[txSize];
  810. ref Array2<Array2<Array6<Array6<Array3<byte>>>>> preProbs = ref preFc.CoefProbs[txSize];
  811. ref Array2<Array2<Array6<Array6<Array4<uint>>>>> counts = ref Counts.Value.Coef[txSize];
  812. ref Array2<Array2<Array6<Array6<uint>>>> eobCounts = ref Counts.Value.EobBranch[txSize];
  813. for (int i = 0; i < Constants.PlaneTypes; ++i)
  814. {
  815. for (int j = 0; j < Entropy.RefTypes; ++j)
  816. {
  817. for (int k = 0; k < Entropy.CoefBands; ++k)
  818. {
  819. for (int l = 0; l < Entropy.BAND_COEFF_CONTEXTS(k); ++l)
  820. {
  821. int n0 = (int)counts[i][j][k][l][Entropy.ZeroToken];
  822. int n1 = (int)counts[i][j][k][l][Entropy.OneToken];
  823. int n2 = (int)counts[i][j][k][l][Entropy.TwoToken];
  824. int neob = (int)counts[i][j][k][l][Entropy.EobModelToken];
  825. Array3<Array2<uint>> branchCt = new();
  826. branchCt[0][0] = (uint)neob;
  827. branchCt[0][1] = (uint)(eobCounts[i][j][k][l] - neob);
  828. branchCt[1][0] = (uint)n0;
  829. branchCt[1][1] = (uint)(n1 + n2);
  830. branchCt[2][0] = (uint)n1;
  831. branchCt[2][1] = (uint)n2;
  832. for (int m = 0; m < Entropy.UnconstrainedNodes; ++m)
  833. {
  834. probs[i][j][k][l][m] = Prob.MergeProbs(preProbs[i][j][k][l][m], ref branchCt[m],
  835. countSat, updateFactor);
  836. }
  837. }
  838. }
  839. }
  840. }
  841. }
  842. public void DefaultCoefProbs()
  843. {
  844. Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx4x4], Entropy.DefaultCoefProbs4x4);
  845. Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx8x8], Entropy.DefaultCoefProbs8x8);
  846. Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx16x16], Entropy.DefaultCoefProbs16x16);
  847. Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx32x32], Entropy.DefaultCoefProbs32x32);
  848. }
  849. }
  850. }