1 /*
2 * Copyright (c) 2020-2023, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     encode_vp9_hpu.cpp
24 //! \brief    Defines the common interface for vp9 encode hpu (header probability update) features
25 //!
26 
27 #include "encode_vp9_hpu.h"
28 #include "encode_vp9_pak.h"
29 #include "encode_vp9_vdenc_feature_manager.h"
30 #include "encode_vp9_vdenc_const_settings.h"
31 #include "media_vp9_packet_defs.h"
32 
33 namespace encode
34 {
35 const uint32_t Vp9EncodeHpu::m_probDmem[320] = {
36     0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
37     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000,
38     0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
39     0x00000004, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
40     0x00000000, 0x00000000, 0x00000000, 0x01000000, 0x0000FF00, 0x00000000, 0x00000000, 0x00000000,
41     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001,
42     0x00540049, 0x00000060, 0x00000072, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
43     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
44     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
45     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
46     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
47     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
48     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
49     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
50     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
51     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
52     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
53     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
54     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
55     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
56     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
57     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
58     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
59     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
60     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
61     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
62     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
63     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
64     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
65     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
66     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
67     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
68     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
69     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
70     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
71     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
72     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
73     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
74     0x00000000, 0x00000000, 0x00000000, 0x02B80078, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
75     0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
76 };
77 
Vp9EncodeHpu(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)78 Vp9EncodeHpu::Vp9EncodeHpu(
79     MediaFeatureManager *featureManager,
80     EncodeAllocator *    allocator,
81     CodechalHwInterfaceNext *hwInterface,
82     void *               constSettings)
83     : MediaFeature(constSettings),
84       m_allocator(allocator)
85 {
86     ENCODE_FUNC_CALL();
87     ENCODE_CHK_NULL_NO_STATUS_RETURN(featureManager);
88 
89     m_featureManager = featureManager;
90     auto encFeatureManager = dynamic_cast<EncodeVp9VdencFeatureManager *>(featureManager);
91     ENCODE_CHK_NULL_NO_STATUS_RETURN(encFeatureManager);
92 
93     m_basicFeature = dynamic_cast<Vp9BasicFeature *>(encFeatureManager->GetFeature(FeatureIDs::basicFeature));
94     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
95 }
96 
Init(void * settings)97 MOS_STATUS Vp9EncodeHpu::Init(void *settings)
98 {
99     ENCODE_FUNC_CALL();
100 
101     m_enabled = true;
102 
103     ENCODE_CHK_STATUS_RETURN(AllocateResources());
104 
105     return MOS_STATUS_SUCCESS;
106 }
107 
Update(void * params)108 MOS_STATUS Vp9EncodeHpu::Update(void *params)
109 {
110     ENCODE_FUNC_CALL();
111     ENCODE_CHK_NULL_RETURN(params);
112 
113     EncoderParams *encodeParams = (EncoderParams *)params;
114 
115     auto vp9SeqParams = static_cast<PCODEC_VP9_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams);
116     ENCODE_CHK_NULL_RETURN(vp9SeqParams);
117     auto vp9PicParams = static_cast<PCODEC_VP9_ENCODE_PIC_PARAMS>(encodeParams->pPicParams);
118     ENCODE_CHK_NULL_RETURN(vp9PicParams);
119 
120     if (m_basicFeature->m_newSeq)
121     {
122         ENCODE_CHK_STATUS_RETURN(SetConstSettings());
123     }
124 
125     // Initialize huc prob dmem buffers in the first pass.
126     for (auto i = 0; i < 3; ++i)
127     {
128         auto dmem = (HucProbDmem *)m_allocator->LockResourceForWrite(
129             &m_resHucProbDmemBuffer[m_basicFeature->m_currRecycledBufIdx][i]);
130         ENCODE_CHK_NULL_RETURN(dmem);
131 
132         MOS_SecureMemcpy(dmem, sizeof(HucProbDmem), m_probDmem, sizeof(HucProbDmem));
133 
134         ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(
135             &m_resHucProbDmemBuffer[m_basicFeature->m_currRecycledBufIdx][i]));
136     }
137 
138     return MOS_STATUS_SUCCESS;
139 }
140 
SetRegions(mhw::vdbox::huc::HUC_VIRTUAL_ADDR_STATE_PAR & params) const141 MOS_STATUS Vp9EncodeHpu::SetRegions(mhw::vdbox::huc::HUC_VIRTUAL_ADDR_STATE_PAR &params) const
142 {
143     ENCODE_FUNC_CALL();
144 
145     auto frameCtxtIdx = m_basicFeature->m_vp9PicParams->PicFlags.fields.frame_context_idx;
146 
147     // Input regions: 0,1
148 
149     params.regionParams[0].presRegion = const_cast<MOS_RESOURCE *>(&m_resProbBuffer[frameCtxtIdx]);
150     params.regionParams[0].isWritable = true;  // Region 0 is both read and write for HuC.
151                                                // Has input probabilities before running HuC and updated
152                                                // probabilities after running HuC, which will then be input to next pass
153     params.regionParams[1].presRegion = const_cast<MOS_RESOURCE *>(&m_resProbabilityCounterBuffer);
154     params.regionParams[1].dwOffset   = 0;
155 
156     // Output regions: 2,3
157     // Final probability output from HuC after each pass
158     params.regionParams[2].presRegion  = const_cast<MOS_RESOURCE *>(&m_resHucProbOutputBuffer);
159     params.regionParams[2].isWritable  = true;
160     params.regionParams[3].presRegion  = const_cast<MOS_RESOURCE *>(&m_resProbabilityDeltaBuffer);
161     params.regionParams[3].isWritable  = true;
162 
163     return MOS_STATUS_SUCCESS;
164 }
165 
GetProbabilityBuffer(uint32_t idx,PMOS_RESOURCE & buffer)166 MOS_STATUS Vp9EncodeHpu::GetProbabilityBuffer(uint32_t idx, PMOS_RESOURCE &buffer)
167 {
168     ENCODE_FUNC_CALL();
169 
170     if (idx >= CODEC_VP9_NUM_CONTEXTS)
171     {
172         ENCODE_ASSERTMESSAGE("Index exceeds the max number, when try to get resProbBuffer");
173         return MOS_STATUS_INVALID_PARAMETER;
174     }
175 
176     buffer = &m_resProbBuffer[idx];
177 
178     return MOS_STATUS_SUCCESS;
179 }
180 
GetHucProbDmemBuffer(uint32_t idx,PMOS_RESOURCE & buffer)181 MOS_STATUS Vp9EncodeHpu::GetHucProbDmemBuffer(uint32_t idx, PMOS_RESOURCE &buffer)
182 {
183     ENCODE_FUNC_CALL();
184 
185     if (idx >= 3)
186     {
187         ENCODE_ASSERTMESSAGE("Index exceeds the max number, when try to get resHucProbDmemBuffer");
188         return MOS_STATUS_INVALID_PARAMETER;
189     }
190 
191     buffer = &m_resHucProbDmemBuffer[m_basicFeature->m_currRecycledBufIdx][idx];
192 
193     return MOS_STATUS_SUCCESS;
194 }
195 
AllocateResources()196 MOS_STATUS Vp9EncodeHpu::AllocateResources()
197 {
198     ENCODE_FUNC_CALL();
199     ENCODE_CHK_NULL_RETURN(m_basicFeature);
200 
201     MOS_RESOURCE *allocatedBuffer = nullptr;
202 
203     // Initiate allocation parameters and lock flags
204     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
205     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
206     allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
207     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
208     allocParamsForBufferLinear.Format   = Format_Buffer;
209 
210     // Probability delta buffer
211     allocParamsForBufferLinear.dwBytes  = 29 * CODECHAL_CACHELINE_SIZE;
212     allocParamsForBufferLinear.pBufName = "ProbabilityDeltaBuffer";
213     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ;
214     allocatedBuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
215     ENCODE_CHK_NULL_RETURN(allocatedBuffer);
216     m_resProbabilityDeltaBuffer = *allocatedBuffer;
217 
218     // Probability counter buffer
219     allocParamsForBufferLinear.dwBytes  = m_probabilityCounterBufferSize * m_basicFeature->m_maxTileNumber;
220     allocParamsForBufferLinear.pBufName = "ProbabilityCounterBuffer";
221     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
222     allocatedBuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
223     ENCODE_CHK_NULL_RETURN(allocatedBuffer);
224     m_resProbabilityCounterBuffer = *allocatedBuffer;
225 
226     // Huc Prob DMEM buffer
227     allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(MOS_MAX(sizeof(HucProbDmem), sizeof(HucProbDmem)), CODECHAL_CACHELINE_SIZE);
228     allocParamsForBufferLinear.pBufName = "HucProbDmemBuffer";
229     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
230     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; ++i)
231     {
232         for (auto j = 0; j < 3; ++j)
233         {
234             allocatedBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
235             ENCODE_CHK_NULL_RETURN(allocatedBuffer);
236             m_resHucProbDmemBuffer[i][j] = *allocatedBuffer;
237         }
238     }
239 
240     // Huc probability output buffer
241     allocParamsForBufferLinear.dwBytes  = 32 * CODECHAL_CACHELINE_SIZE;
242     allocParamsForBufferLinear.pBufName = "HucProbabilityOutputBuffer";
243     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ;
244     allocatedBuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
245     ENCODE_CHK_NULL_RETURN(allocatedBuffer);
246     m_resHucProbOutputBuffer = *allocatedBuffer;
247 
248     // Probability buffers
249     allocParamsForBufferLinear.dwBytes  = 32 * CODECHAL_CACHELINE_SIZE;
250     allocParamsForBufferLinear.pBufName = "ProbabilityBuffer";
251     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
252     for (auto i = 0; i < CODEC_VP9_NUM_CONTEXTS; ++i)
253     {
254         allocatedBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
255         ENCODE_CHK_NULL_RETURN(allocatedBuffer);
256         m_resProbBuffer[i] = *allocatedBuffer;
257     }
258 
259     return MOS_STATUS_SUCCESS;
260 }
261 
SetIsLastPass(bool isLastPass)262 MOS_STATUS Vp9EncodeHpu::SetIsLastPass(bool isLastPass)
263 {
264     m_isLastPass = isLastPass;
265 
266     return MOS_STATUS_SUCCESS;
267 }
268 
MHW_SETPAR_DECL_SRC(HCP_IND_OBJ_BASE_ADDR_STATE,Vp9EncodeHpu)269 MHW_SETPAR_DECL_SRC(HCP_IND_OBJ_BASE_ADDR_STATE, Vp9EncodeHpu)
270 {
271     ENCODE_FUNC_CALL();
272 
273     auto basicFeature = dynamic_cast<Vp9BasicFeature *>(m_basicFeature);
274     ENCODE_CHK_NULL_RETURN(basicFeature);
275 
276     params.presProbabilityDeltaBuffer = const_cast<PMOS_RESOURCE>(&m_resProbabilityDeltaBuffer);
277     params.dwProbabilityDeltaSize     = 29 * CODECHAL_CACHELINE_SIZE;
278 
279     if (!basicFeature->m_scalableMode)
280     {
281         params.presProbabilityCounterBuffer = const_cast<PMOS_RESOURCE>(&m_resProbabilityCounterBuffer);
282         params.dwProbabilityCounterOffset   = 0;
283         params.dwProbabilityCounterSize     = 193 * CODECHAL_CACHELINE_SIZE;
284     }
285 
286     return MOS_STATUS_SUCCESS;
287 }
288 
MHW_SETPAR_DECL_SRC(HCP_PIPE_BUF_ADDR_STATE,Vp9EncodeHpu)289 MHW_SETPAR_DECL_SRC(HCP_PIPE_BUF_ADDR_STATE, Vp9EncodeHpu)
290 {
291     ENCODE_FUNC_CALL();
292 
293     // Huc first pass doesn't write probabilities to output prob region but only updates to the input region.
294     // HuC run before repak writes to the ouput region.
295     if (m_basicFeature->m_hucEnabled && m_isLastPass)
296     {
297         params.presVp9ProbBuffer = const_cast<PMOS_RESOURCE>(&m_resHucProbOutputBuffer);
298     }
299     else
300     {
301         auto frameCtxIdx = m_basicFeature->m_vp9PicParams->PicFlags.fields.frame_context_idx;
302         ENCODE_ASSERT(frameCtxIdx < CODEC_VP9_NUM_CONTEXTS);
303         params.presVp9ProbBuffer = const_cast<PMOS_RESOURCE>(&m_resProbBuffer[frameCtxIdx]);
304     }
305 
306     return MOS_STATUS_SUCCESS;
307 }
308 
SetDefaultTxProbs(uint8_t * ctxBuffer,uint32_t & byteCnt) const309 MOS_STATUS Vp9EncodeHpu::SetDefaultTxProbs(uint8_t *ctxBuffer, uint32_t &byteCnt) const
310 {
311     ENCODE_FUNC_CALL();
312 
313     int32_t i, j;
314     // TX probs
315     for (i = 0; i < CODEC_VP9_TX_SIZE_CONTEXTS; ++i)
316     {
317         for (j = 0; j < CODEC_VP9_TX_SIZES - 3; ++j)
318         {
319             ctxBuffer[byteCnt++] = DefaultTxProbs.p8x8[i][j];
320         }
321     }
322     for (i = 0; i < CODEC_VP9_TX_SIZE_CONTEXTS; ++i)
323     {
324         for (j = 0; j < CODEC_VP9_TX_SIZES - 2; ++j)
325         {
326             ctxBuffer[byteCnt++] = DefaultTxProbs.p16x16[i][j];
327         }
328     }
329     for (i = 0; i < CODEC_VP9_TX_SIZE_CONTEXTS; ++i)
330     {
331         for (j = 0; j < CODEC_VP9_TX_SIZES - 1; ++j)
332         {
333             ctxBuffer[byteCnt++] = DefaultTxProbs.p32x32[i][j];
334         }
335     }
336 
337     return MOS_STATUS_SUCCESS;
338 }
339 
SetDefaultCoeffProbs(uint8_t * ctxBuffer,uint32_t & byteCnt) const340 MOS_STATUS Vp9EncodeHpu::SetDefaultCoeffProbs(uint8_t *ctxBuffer, uint32_t &byteCnt) const
341 {
342     ENCODE_FUNC_CALL();
343 
344     uint8_t blocktype          = 0;
345     uint8_t reftype            = 0;
346     uint8_t coeffbands         = 0;
347     uint8_t unConstrainedNodes = 0;
348     uint8_t prevCoefCtx        = 0;
349     // Coeff probs
350     for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; ++blocktype)
351     {
352         for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; ++reftype)
353         {
354             for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; ++coeffbands)
355             {
356                 uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS;
357                 for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; ++prevCoefCtx)
358                 {
359                     for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; ++unConstrainedNodes)
360                     {
361                         ctxBuffer[byteCnt++] = DefaultCoefProbs4x4[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes];
362                     }
363                 }
364             }
365         }
366     }
367 
368     for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; ++blocktype)
369     {
370         for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; ++reftype)
371         {
372             for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; ++coeffbands)
373             {
374                 uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS;
375                 for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; ++prevCoefCtx)
376                 {
377                     for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; ++unConstrainedNodes)
378                     {
379                         ctxBuffer[byteCnt++] = DefaultCoefPprobs8x8[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes];
380                     }
381                 }
382             }
383         }
384     }
385 
386     for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; ++blocktype)
387     {
388         for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; ++reftype)
389         {
390             for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; ++coeffbands)
391             {
392                 uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS;
393                 for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; ++prevCoefCtx)
394                 {
395                     for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; ++unConstrainedNodes)
396                     {
397                         ctxBuffer[byteCnt++] = DefaultCoefProbs16x16[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes];
398                     }
399                 }
400             }
401         }
402     }
403 
404     for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; ++blocktype)
405     {
406         for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; ++reftype)
407         {
408             for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; ++coeffbands)
409             {
410                 uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS;
411                 for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; ++prevCoefCtx)
412                 {
413                     for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; ++unConstrainedNodes)
414                     {
415                         ctxBuffer[byteCnt++] = DefaultCoefProbs32x32[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes];
416                     }
417                 }
418             }
419         }
420     }
421 
422     return MOS_STATUS_SUCCESS;
423 }
424 
SetDefaultMbskipProbs(uint8_t * ctxBuffer,uint32_t & byteCnt) const425 MOS_STATUS Vp9EncodeHpu::SetDefaultMbskipProbs(uint8_t *ctxBuffer, uint32_t &byteCnt) const
426 {
427     ENCODE_FUNC_CALL();
428 
429     // mb skip probs
430     for (auto i = 0; i < CODEC_VP9_MBSKIP_CONTEXTS; ++i)
431     {
432         ctxBuffer[byteCnt++] = DefaultMbskipProbs[i];
433     }
434 
435     return MOS_STATUS_SUCCESS;
436 }
437 
SetDefaultInterModeProbs(uint8_t * ctxBuffer,uint32_t & byteCnt,bool setToKey) const438 MOS_STATUS Vp9EncodeHpu::SetDefaultInterModeProbs(uint8_t *ctxBuffer, uint32_t &byteCnt, bool setToKey) const
439 {
440     ENCODE_FUNC_CALL();
441 
442     int32_t i, j;
443 
444     // Inter mode probs
445     for (i = 0; i < CODEC_VP9_INTER_MODE_CONTEXTS; ++i)
446     {
447         for (j = 0; j < CODEC_VP9_INTER_MODES - 1; ++j)
448         {
449             if (!setToKey)
450             {
451                 ctxBuffer[byteCnt++] = DefaultInterModeProbs[i][j];
452             }
453             else
454             {
455                 // Zeros for key frame
456                 byteCnt++;
457             }
458         }
459     }
460 
461     return MOS_STATUS_SUCCESS;
462 }
463 
SetDefaultSwitchableInterpProb(uint8_t * ctxBuffer,uint32_t & byteCnt,bool setToKey) const464 MOS_STATUS Vp9EncodeHpu::SetDefaultSwitchableInterpProb(uint8_t *ctxBuffer, uint32_t &byteCnt, bool setToKey) const
465 {
466     ENCODE_FUNC_CALL();
467 
468     int32_t i, j;
469 
470     // Switchable interprediction probs
471     for (i = 0; i < CODEC_VP9_SWITCHABLE_FILTERS + 1; ++i)
472     {
473         for (j = 0; j < CODEC_VP9_SWITCHABLE_FILTERS - 1; ++j)
474         {
475             if (!setToKey)
476             {
477                 ctxBuffer[byteCnt++] = DefaultSwitchableInterpProb[i][j];
478             }
479             else
480             {
481                 // Zeros for key frame
482                 byteCnt++;
483             }
484         }
485     }
486 
487     return MOS_STATUS_SUCCESS;
488 }
489 
SetDefaultIntraInterProb(uint8_t * ctxBuffer,uint32_t & byteCnt,bool setToKey) const490 MOS_STATUS Vp9EncodeHpu::SetDefaultIntraInterProb(uint8_t *ctxBuffer, uint32_t &byteCnt, bool setToKey) const
491 {
492     ENCODE_FUNC_CALL();
493 
494     // Intra inter probs
495     for (auto i = 0; i < CODEC_VP9_INTRA_INTER_CONTEXTS; ++i)
496     {
497         if (!setToKey)
498         {
499             ctxBuffer[byteCnt++] = DefaultIntraInterProb[i];
500         }
501         else
502         {
503             // Zeros for key frame
504             byteCnt++;
505         }
506     }
507 
508     return MOS_STATUS_SUCCESS;
509 }
510 
SetDefaultCompInterProb(uint8_t * ctxBuffer,uint32_t & byteCnt,bool setToKey) const511 MOS_STATUS Vp9EncodeHpu::SetDefaultCompInterProb(uint8_t *ctxBuffer, uint32_t &byteCnt, bool setToKey) const
512 {
513     ENCODE_FUNC_CALL();
514 
515     // Comp inter probs
516     for (auto i = 0; i < CODEC_VP9_COMP_INTER_CONTEXTS; ++i)
517     {
518         if (!setToKey)
519         {
520             ctxBuffer[byteCnt++] = DefaultCompInterProb[i];
521         }
522         else
523         {
524             // Zeros for key frame
525             byteCnt++;
526         }
527     }
528 
529     return MOS_STATUS_SUCCESS;
530 }
531 
SetDefaultSingleRefProb(uint8_t * ctxBuffer,uint32_t & byteCnt,bool setToKey) const532 MOS_STATUS Vp9EncodeHpu::SetDefaultSingleRefProb(uint8_t *ctxBuffer, uint32_t &byteCnt, bool setToKey) const
533 {
534     ENCODE_FUNC_CALL();
535 
536     int32_t i, j;
537 
538     // Single ref probs
539     for (i = 0; i < CODEC_VP9_REF_CONTEXTS; ++i)
540     {
541         for (j = 0; j < 2; ++j)
542         {
543             if (!setToKey)
544             {
545                 ctxBuffer[byteCnt++] = DefaultSingleRefProb[i][j];
546             }
547             else
548             {
549                 // Zeros for key frame
550                 byteCnt++;
551             }
552         }
553     }
554 
555     return MOS_STATUS_SUCCESS;
556 }
557 
SetDefaultCompRefProb(uint8_t * ctxBuffer,uint32_t & byteCnt,bool setToKey) const558 MOS_STATUS Vp9EncodeHpu::SetDefaultCompRefProb(uint8_t *ctxBuffer, uint32_t &byteCnt, bool setToKey) const
559 {
560     ENCODE_FUNC_CALL();
561 
562     // Comp ref probs
563     for (auto i = 0; i < CODEC_VP9_REF_CONTEXTS; ++i)
564     {
565         if (!setToKey)
566         {
567             ctxBuffer[byteCnt++] = DefaultCompRefProb[i];
568         }
569         else
570         {
571             // Zeros for key frame
572             byteCnt++;
573         }
574     }
575 
576     return MOS_STATUS_SUCCESS;
577 }
578 
SetDefaultYModeProb(uint8_t * ctxBuffer,uint32_t & byteCnt,bool setToKey) const579 MOS_STATUS Vp9EncodeHpu::SetDefaultYModeProb(uint8_t *ctxBuffer, uint32_t &byteCnt, bool setToKey) const
580 {
581     ENCODE_FUNC_CALL();
582 
583     int32_t i, j;
584 
585     // y mode probs
586     for (i = 0; i < CODEC_VP9_BLOCK_SIZE_GROUPS; ++i)
587     {
588         for (j = 0; j < CODEC_VP9_INTRA_MODES - 1; ++j)
589         {
590             if (!setToKey)
591             {
592                 ctxBuffer[byteCnt++] = DefaultIFYProb[i][j];
593             }
594             else
595             {
596                 // Zeros for key frame, since HW will not use this buffer, but default right buffer
597                 byteCnt++;
598             }
599         }
600     }
601 
602     return MOS_STATUS_SUCCESS;
603 }
604 
SetDefaultPartitionProb(uint8_t * ctxBuffer,uint32_t & byteCnt,bool setToKey) const605 MOS_STATUS Vp9EncodeHpu::SetDefaultPartitionProb(uint8_t *ctxBuffer, uint32_t &byteCnt, bool setToKey) const
606 {
607     ENCODE_FUNC_CALL();
608 
609     int32_t i, j;
610 
611     // Partition probs, key & intra-only frames use key type, other inter frames use inter type
612     for (i = 0; i < CODECHAL_VP9_PARTITION_CONTEXTS; ++i)
613     {
614         for (j = 0; j < CODEC_VP9_PARTITION_TYPES - 1; ++j)
615         {
616             if (setToKey)
617             {
618                 ctxBuffer[byteCnt++] = DefaultKFPartitionProb[i][j];
619             }
620             else
621             {
622                 ctxBuffer[byteCnt++] = DefaultPartitionProb[i][j];
623             }
624         }
625     }
626 
627     return MOS_STATUS_SUCCESS;
628 }
629 
SetDefaultNmvContext(uint8_t * ctxBuffer,uint32_t & byteCnt,bool setToKey) const630 MOS_STATUS Vp9EncodeHpu::SetDefaultNmvContext(uint8_t *ctxBuffer, uint32_t &byteCnt, bool setToKey) const
631 {
632     ENCODE_FUNC_CALL();
633 
634     int32_t i, j;
635 
636     for (i = 0; i < (CODEC_VP9_MV_JOINTS - 1); ++i)
637     {
638         if (!setToKey)
639         {
640             ctxBuffer[byteCnt++] = DefaultNmvContext.joints[i];
641         }
642         else
643         {
644             byteCnt++;
645         }
646     }
647 
648     for (i = 0; i < 2; ++i)
649     {
650         if (!setToKey)
651         {
652             ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].sign;
653             for (j = 0; j < (CODEC_VP9_MV_CLASSES - 1); ++j)
654             {
655                 ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].classes[j];
656             }
657             for (j = 0; j < (CODECHAL_VP9_CLASS0_SIZE - 1); ++j)
658             {
659                 ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].class0[j];
660             }
661             for (j = 0; j < CODECHAL_VP9_MV_OFFSET_BITS; ++j)
662             {
663                 ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].bits[j];
664             }
665         }
666         else
667         {
668             byteCnt += 1;
669             byteCnt += (CODEC_VP9_MV_CLASSES - 1);
670             byteCnt += (CODECHAL_VP9_CLASS0_SIZE - 1);
671             byteCnt += (CODECHAL_VP9_MV_OFFSET_BITS);
672         }
673     }
674     for (i = 0; i < 2; ++i)
675     {
676         if (!setToKey)
677         {
678             for (j = 0; j < CODECHAL_VP9_CLASS0_SIZE; ++j)
679             {
680                 for (int32_t k = 0; k < (CODEC_VP9_MV_FP_SIZE - 1); ++k)
681                 {
682                     ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].class0_fp[j][k];
683                 }
684             }
685             for (j = 0; j < (CODEC_VP9_MV_FP_SIZE - 1); ++j)
686             {
687                 ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].fp[j];
688             }
689         }
690         else
691         {
692             byteCnt += (CODECHAL_VP9_CLASS0_SIZE * (CODEC_VP9_MV_FP_SIZE - 1));
693             byteCnt += (CODEC_VP9_MV_FP_SIZE - 1);
694         }
695     }
696     for (i = 0; i < 2; ++i)
697     {
698         if (!setToKey)
699         {
700             ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].class0_hp;
701             ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].hp;
702         }
703         else
704         {
705             byteCnt += 2;
706         }
707     }
708 
709     return MOS_STATUS_SUCCESS;
710 }
711 
SetDefaultUVModeProbs(uint8_t * ctxBuffer,uint32_t & byteCnt,bool setToKey) const712 MOS_STATUS Vp9EncodeHpu::SetDefaultUVModeProbs(uint8_t *ctxBuffer, uint32_t &byteCnt, bool setToKey) const
713 {
714     ENCODE_FUNC_CALL();
715 
716     int32_t i, j;
717 
718     // uv mode probs
719     for (i = 0; i < CODEC_VP9_INTRA_MODES; ++i)
720     {
721         for (j = 0; j < CODEC_VP9_INTRA_MODES - 1; ++j)
722         {
723             if (setToKey)
724             {
725                 ctxBuffer[byteCnt++] = DefaultKFUVModeProb[i][j];
726             }
727             else
728             {
729                 ctxBuffer[byteCnt++] = DefaultIFUVProbs[i][j];
730             }
731         }
732     }
733 
734     return MOS_STATUS_SUCCESS;
735 }
736 
CtxBufDiffInit(uint8_t * ctxBuffer,bool setToKey) const737 MOS_STATUS Vp9EncodeHpu::CtxBufDiffInit(uint8_t *ctxBuffer, bool setToKey) const
738 {
739     ENCODE_FUNC_CALL();
740 
741     uint32_t byteCnt = CODEC_VP9_INTER_PROB_OFFSET;
742 
743     ENCODE_CHK_STATUS_RETURN(SetDefaultInterModeProbs(ctxBuffer, byteCnt, setToKey));
744 
745     ENCODE_CHK_STATUS_RETURN(SetDefaultSwitchableInterpProb(ctxBuffer, byteCnt, setToKey));
746 
747     ENCODE_CHK_STATUS_RETURN(SetDefaultIntraInterProb(ctxBuffer, byteCnt, setToKey));
748 
749     ENCODE_CHK_STATUS_RETURN(SetDefaultCompInterProb(ctxBuffer, byteCnt, setToKey));
750 
751     ENCODE_CHK_STATUS_RETURN(SetDefaultSingleRefProb(ctxBuffer, byteCnt, setToKey));
752 
753     ENCODE_CHK_STATUS_RETURN(SetDefaultCompRefProb(ctxBuffer, byteCnt, setToKey));
754 
755     ENCODE_CHK_STATUS_RETURN(SetDefaultYModeProb(ctxBuffer, byteCnt, setToKey));
756 
757     ENCODE_CHK_STATUS_RETURN(SetDefaultPartitionProb(ctxBuffer, byteCnt, setToKey));
758 
759     ENCODE_CHK_STATUS_RETURN(SetDefaultNmvContext(ctxBuffer, byteCnt, setToKey));
760 
761     // 47 bytes of zeros
762     byteCnt += 47;
763 
764     ENCODE_CHK_STATUS_RETURN(SetDefaultUVModeProbs(ctxBuffer, byteCnt, setToKey));
765 
766     return MOS_STATUS_SUCCESS;
767 }
768 
ContextBufferInit(uint8_t * ctxBuffer,bool setToKey) const769 MOS_STATUS Vp9EncodeHpu::ContextBufferInit(uint8_t *ctxBuffer, bool setToKey) const
770 {
771     ENCODE_FUNC_CALL();
772 
773     MOS_ZeroMemory(ctxBuffer, CODEC_VP9_SEG_PROB_OFFSET);
774 
775     uint32_t byteCnt = 0;
776 
777     ENCODE_CHK_STATUS_RETURN(SetDefaultTxProbs(ctxBuffer, byteCnt));
778 
779     // 52 bytes of zeros
780     byteCnt += 52;
781 
782     ENCODE_CHK_STATUS_RETURN(SetDefaultCoeffProbs(ctxBuffer, byteCnt));
783 
784     // 16 bytes of zeros
785     byteCnt += 16;
786 
787     ENCODE_CHK_STATUS_RETURN(SetDefaultMbskipProbs(ctxBuffer, byteCnt));
788 
789     // Populate prob values which are different between Key and Non-Key frame
790     CtxBufDiffInit(ctxBuffer, setToKey);
791 
792     // Skip Seg tree/pred probs, updating not done in this function
793     byteCnt = CODEC_VP9_SEG_PROB_OFFSET;
794     byteCnt += 7;
795     byteCnt += 3;
796 
797     // 28 bytes of zeros
798     for (auto i = 0; i < 28; i++)
799     {
800         ctxBuffer[byteCnt++] = 0;
801     }
802 
803     if (byteCnt > CODEC_VP9_PROB_MAX_NUM_ELEM)
804     {
805         CODECHAL_PUBLIC_ASSERTMESSAGE("Error: FrameContext array out-of-bounds, byteCnt = %d!\n", byteCnt);
806         return MOS_STATUS_NO_SPACE;
807     }
808     else
809     {
810         return MOS_STATUS_SUCCESS;
811     }
812 }
813 
PutDataForCompressedHdr(CompressedHeader * compressedHdr,uint32_t bit,uint32_t prob,uint32_t binIdx)814 void Vp9EncodeHpu::PutDataForCompressedHdr(
815     CompressedHeader *compressedHdr,
816     uint32_t          bit,
817     uint32_t          prob,
818     uint32_t          binIdx)
819 {
820     compressedHdr[binIdx].fields.valid        = 1;
821     compressedHdr[binIdx].fields.bin_probdiff = 1;
822     compressedHdr[binIdx].fields.bin          = bit;
823     compressedHdr[binIdx].fields.prob         = (prob == 128) ? 0 : 1;
824 }
825 
RefreshFrameInternalBuffers()826 MOS_STATUS Vp9EncodeHpu::RefreshFrameInternalBuffers()
827 {
828     ENCODE_FUNC_CALL();
829     ENCODE_CHK_NULL_RETURN(m_basicFeature);
830     ENCODE_CHK_NULL_RETURN(m_basicFeature->m_vp9PicParams);
831 
832     auto hpuFeature = dynamic_cast<Vp9EncodeHpu *>(m_featureManager->GetFeature(Vp9FeatureIDs::vp9HpuFeature));
833     ENCODE_CHK_NULL_RETURN(hpuFeature);
834     auto pakFeature = dynamic_cast<Vp9EncodePak *>(m_featureManager->GetFeature(Vp9FeatureIDs::vp9PakFeature));
835     ENCODE_CHK_NULL_RETURN(pakFeature);
836 
837     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
838 
839     auto &picFields = m_basicFeature->m_vp9PicParams->PicFlags.fields;
840     ENCODE_ASSERT(picFields.refresh_frame_context == 0);
841 
842     MOS_LOCK_PARAMS lockFlagsWriteOnly;
843     MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
844     lockFlagsWriteOnly.WriteOnly = 1;
845 
846     bool keyFrame      = !picFields.frame_type;
847     bool isScaling     = (m_basicFeature->m_oriFrameWidth == m_basicFeature->m_prevFrameInfo.FrameWidth) &&
848                              (m_basicFeature->m_oriFrameHeight == m_basicFeature->m_prevFrameInfo.FrameHeight)
849                              ? false
850                              : true;
851     bool resetSegIdBuf = keyFrame || isScaling ||
852                          picFields.error_resilient_mode ||
853                          picFields.intra_only;
854 
855     if (resetSegIdBuf)
856     {
857         uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(m_basicFeature->m_resSegmentIdBuffer);
858         ENCODE_CHK_NULL_RETURN(data);
859 
860         MOS_ZeroMemory(data, m_basicFeature->m_picSizeInSb * CODECHAL_CACHELINE_SIZE);
861 
862         ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(m_basicFeature->m_resSegmentIdBuffer));
863     }
864 
865     //refresh inter probs in needed frame context buffers
866     bool clearAll = (keyFrame || picFields.error_resilient_mode ||
867                      (picFields.reset_frame_context == 3 && picFields.intra_only));
868 
869     bool clearSpecified = (picFields.reset_frame_context == 2 &&
870                            picFields.intra_only);
871 
872     for (auto i = 0; i < CODEC_VP9_NUM_CONTEXTS; i++)
873     {
874         PMOS_RESOURCE resProbBuffer = nullptr;
875         ENCODE_CHK_STATUS_RETURN(hpuFeature->GetProbabilityBuffer(i, resProbBuffer));
876         ENCODE_CHK_NULL_RETURN(resProbBuffer);
877 
878         if (clearAll || (clearSpecified && i == picFields.frame_context_idx))
879         {
880             uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(resProbBuffer);
881             ENCODE_CHK_NULL_RETURN(data);
882 
883             eStatus = ContextBufferInit(data, keyFrame || picFields.intra_only);
884 
885             ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(resProbBuffer));
886             ENCODE_CHK_STATUS_RETURN(eStatus);
887 
888             m_clearAllToKey[i] = keyFrame || picFields.intra_only;
889             if (i == 0)  //reset this flag when Ctx buffer 0 is cleared.
890             {
891                 m_isPreCtx0InterProbSaved = false;
892             }
893         }
894         else if (m_clearAllToKey[i])  // this buffer is inside inter frame, but its interProb has not been init to default inter type data.
895         {
896             uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(resProbBuffer);
897             ENCODE_CHK_NULL_RETURN(data);
898 
899             if (picFields.intra_only && i == 0)  // this buffer is used as intra_only context, do not need to set interprob to be inter type.
900             {
901                 eStatus = CtxBufDiffInit(data, true);
902             }
903             else  // set interprob to be inter type.
904             {
905                 eStatus            = CtxBufDiffInit(data, false);
906                 m_clearAllToKey[i] = false;
907             }
908 
909             ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(resProbBuffer));
910             ENCODE_CHK_STATUS_RETURN(eStatus);
911         }
912         else if (i == 0)  // this buffer do not need to clear in current frame, also it has not been cleared to key type in previous frame.
913         {                 // in this case, only context buffer 0 will be temporally overwritten.
914             if (picFields.intra_only)
915             {
916                 uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(resProbBuffer);
917                 ENCODE_CHK_NULL_RETURN(data);
918 
919                 if (!m_isPreCtx0InterProbSaved)  // only when non intra-only -> intra-only need save InterProb, otherwise leave saved InterProb unchanged.
920                 {
921                     //save current interprob
922                     ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(m_preCtx0InterProbSaved, CODECHAL_VP9_INTER_PROB_SIZE, data + CODEC_VP9_INTER_PROB_OFFSET, CODECHAL_VP9_INTER_PROB_SIZE));
923                     m_isPreCtx0InterProbSaved = true;
924                 }
925                 eStatus = CtxBufDiffInit(data, true);
926                 ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(resProbBuffer));
927                 ENCODE_CHK_STATUS_RETURN(eStatus);
928             }
929             else if (m_isPreCtx0InterProbSaved)
930             {
931                 uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(resProbBuffer);
932                 ENCODE_CHK_NULL_RETURN(data);
933 
934                 //reload former interprob
935                 ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(data + CODEC_VP9_INTER_PROB_OFFSET, CODECHAL_VP9_INTER_PROB_SIZE, m_preCtx0InterProbSaved, CODECHAL_VP9_INTER_PROB_SIZE));
936 
937                 ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(resProbBuffer));
938                 m_isPreCtx0InterProbSaved = false;
939             }
940         }
941     }
942 
943     // compressed header
944     uint32_t          index         = 0;
945     auto              txMode        = m_basicFeature->m_txMode;
946     CompressedHeader *compressedHdr = (CompressedHeader *)MOS_AllocAndZeroMemory(sizeof(CompressedHeader) * (PAK_COMPRESSED_HDR_SYNTAX_ELEMS + 1));
947     ENCODE_CHK_NULL_RETURN(compressedHdr);
948 
949     if (!picFields.LosslessFlag)
950     {
951         if (txMode == CODEC_VP9_TX_SELECTABLE)
952         {
953             PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_TX_MODE_IDX);
954             PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_TX_MODE_IDX + 1);
955             PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_TX_MODE_SELECT_IDX);
956         }
957         else if (txMode == CODEC_VP9_TX_32X32)
958         {
959             PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_TX_MODE_IDX);
960             PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_TX_MODE_IDX + 1);
961             PutDataForCompressedHdr(compressedHdr, 0, 128, PAK_TX_MODE_SELECT_IDX);
962         }
963         else
964         {
965             PutDataForCompressedHdr(compressedHdr, (txMode & 0x02) >> 1, 128, PAK_TX_MODE_IDX);
966             PutDataForCompressedHdr(compressedHdr, (txMode & 0x01), 128, PAK_TX_MODE_IDX + 1);
967         }
968 
969         if (txMode == CODEC_VP9_TX_SELECTABLE)
970         {
971             index = PAK_TX_8x8_PROB_IDX;
972             for (auto i = 0; i < 2; i++)
973             {
974                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
975                 index += 2;
976             }
977 
978             index = PAK_TX_16x16_PROB_IDX;
979             for (auto i = 0; i < 2; i++)
980             {
981                 for (auto j = 0; j < 2; j++)
982                 {
983                     PutDataForCompressedHdr(compressedHdr, 0, 252, index);
984                     index += 2;
985                 }
986             }
987 
988             index = PAK_TX_32x32_PROB_IDX;
989             for (auto i = 0; i < 2; i++)
990             {
991                 for (auto j = 0; j < 3; j++)
992                 {
993                     PutDataForCompressedHdr(compressedHdr, 0, 252, index);
994                     index += 2;
995                 }
996             }
997         }
998     }
999 
1000     for (auto coeffSize = 0; coeffSize < 4; coeffSize++)
1001     {
1002         if (coeffSize > txMode)
1003         {
1004             continue;
1005         }
1006 
1007         switch (coeffSize)
1008         {
1009         case 0:
1010             index = PAK_TX_4x4_COEFF_PROB_IDX;
1011             break;
1012         case 1:
1013             index = PAK_TX_8x8_COEFF_PROB_IDX;
1014             break;
1015         case 2:
1016             index = PAK_TX_16x16_COEFF_PROB_IDX;
1017             break;
1018         case 3:
1019             index = PAK_TX_32x32_COEFF_PROB_IDX;
1020             break;
1021         }
1022 
1023         PutDataForCompressedHdr(compressedHdr, 0, 128, index);
1024     }
1025 
1026     PutDataForCompressedHdr(compressedHdr, 0, 252, PAK_SKIP_CONTEXT_IDX);
1027     PutDataForCompressedHdr(compressedHdr, 0, 252, PAK_SKIP_CONTEXT_IDX + 2);
1028     PutDataForCompressedHdr(compressedHdr, 0, 252, PAK_SKIP_CONTEXT_IDX + 4);
1029 
1030     if (picFields.frame_type != 0 && !picFields.intra_only)
1031     {
1032         index = PAK_INTER_MODE_CTX_IDX;
1033         for (auto i = 0; i < 7; i++)
1034         {
1035             for (auto j = 0; j < 3; j++)
1036             {
1037                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1038                 index += 2;
1039             }
1040         }
1041 
1042         if (picFields.mcomp_filter_type == CODEC_VP9_SWITCHABLE_FILTERS)
1043         {
1044             index = PAK_SWITCHABLE_FILTER_CTX_IDX;
1045             for (auto i = 0; i < 4; i++)
1046             {
1047                 for (auto j = 0; j < 2; j++)
1048                 {
1049                     PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1050                     index += 2;
1051                 }
1052             }
1053         }
1054 
1055         index = PAK_INTRA_INTER_CTX_IDX;
1056         for (auto i = 0; i < 4; i++)
1057         {
1058             PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1059             index += 2;
1060         }
1061 
1062         auto &picRefFields = m_basicFeature->m_vp9PicParams->RefFlags.fields;
1063         bool  allowComp    = !(
1064             (picRefFields.LastRefSignBias && picRefFields.GoldenRefSignBias && picRefFields.AltRefSignBias) ||
1065             (!picRefFields.LastRefSignBias && !picRefFields.GoldenRefSignBias && !picRefFields.AltRefSignBias));
1066 
1067         if (allowComp)
1068         {
1069             if (picFields.comp_prediction_mode == PRED_MODE_HYBRID)
1070             {
1071                 PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_COMPOUND_PRED_MODE_IDX);
1072                 PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_COMPOUND_PRED_MODE_IDX + 1);
1073                 index = PAK_HYBRID_PRED_CTX_IDX;
1074                 for (auto i = 0; i < 5; i++)
1075                 {
1076                     PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1077                     index += 2;
1078                 }
1079             }
1080             else if (picFields.comp_prediction_mode == PRED_MODE_COMPOUND)
1081             {
1082                 PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_COMPOUND_PRED_MODE_IDX);
1083                 PutDataForCompressedHdr(compressedHdr, 0, 128, PAK_COMPOUND_PRED_MODE_IDX + 1);
1084             }
1085             else
1086             {
1087                 PutDataForCompressedHdr(compressedHdr, 0, 128, PAK_COMPOUND_PRED_MODE_IDX);
1088             }
1089         }
1090 
1091         if (picFields.comp_prediction_mode != PRED_MODE_COMPOUND)
1092         {
1093             index = PAK_SINGLE_REF_PRED_CTX_IDX;
1094             for (auto i = 0; i < 5; i++)
1095             {
1096                 for (auto j = 0; j < 2; j++)
1097                 {
1098                     PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1099                     index += 2;
1100                 }
1101             }
1102         }
1103 
1104         if (picFields.comp_prediction_mode != PRED_MODE_SINGLE)
1105         {
1106             index = PAK_CMPUND_PRED_CTX_IDX;
1107             for (auto i = 0; i < 5; i++)
1108             {
1109                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1110                 index += 2;
1111             }
1112         }
1113 
1114         index = PAK_INTRA_MODE_PROB_CTX_IDX;
1115         for (auto i = 0; i < 4; i++)
1116         {
1117             for (auto j = 0; j < 9; j++)
1118             {
1119                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1120                 index += 2;
1121             }
1122         }
1123 
1124         index = PAK_PARTITION_PROB_IDX;
1125         for (auto i = 0; i < 16; i++)
1126         {
1127             for (auto j = 0; j < 3; j++)
1128             {
1129                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1130                 index += 2;
1131             }
1132         }
1133 
1134         index = PAK_MVJOINTS_PROB_IDX;
1135         for (auto i = 0; i < 3; i++)
1136         {
1137             PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1138             index += 8;
1139         }
1140 
1141         for (auto d = 0; d < 2; d++)
1142         {
1143             index = (d == 0) ? PAK_MVCOMP0_IDX : PAK_MVCOMP1_IDX;
1144             PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1145             index += 8;
1146             for (auto i = 0; i < 10; i++)
1147             {
1148                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1149                 index += 8;
1150             }
1151             PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1152             index += 8;
1153             for (auto i = 0; i < 10; i++)
1154             {
1155                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1156                 index += 8;
1157             }
1158         }
1159 
1160         for (auto d = 0; d < 2; d++)
1161         {
1162             index = (d == 0) ? PAK_MVFRAC_COMP0_IDX : PAK_MVFRAC_COMP1_IDX;
1163             for (auto i = 0; i < 3; i++)
1164             {
1165                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1166                 index += 8;
1167             }
1168             for (auto i = 0; i < 3; i++)
1169             {
1170                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1171                 index += 8;
1172             }
1173             for (auto i = 0; i < 3; i++)
1174             {
1175                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1176                 index += 8;
1177             }
1178         }
1179 
1180         if (picFields.allow_high_precision_mv)
1181         {
1182             for (auto d = 0; d < 2; d++)
1183             {
1184                 index = (d == 0) ? PAK_MVHP_COMP0_IDX : PAK_MVHP_COMP1_IDX;
1185                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1186                 index += 8;
1187                 PutDataForCompressedHdr(compressedHdr, 0, 252, index);
1188             }
1189         }
1190     }
1191 
1192     PMOS_RESOURCE comprHeaderBuffer = pakFeature->GetCompressedHeaderBuffer();
1193     ENCODE_CHK_NULL_RETURN(comprHeaderBuffer);
1194 
1195     uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(comprHeaderBuffer);
1196     if (data == nullptr)
1197     {
1198         MOS_FreeMemory(compressedHdr);
1199         ENCODE_CHK_NULL_RETURN(nullptr);
1200     }
1201 
1202     for (uint32_t i = 0; i < PAK_COMPRESSED_HDR_SYNTAX_ELEMS; i += 2)
1203     {
1204         data[i >> 1] = (compressedHdr[i + 1].value << 0x04) | (compressedHdr[i].value);
1205     }
1206 
1207     eStatus = m_allocator->UnLock(comprHeaderBuffer);
1208     if (eStatus != MOS_STATUS_SUCCESS)
1209     {
1210         MOS_FreeMemory(compressedHdr);
1211         ENCODE_CHK_STATUS_RETURN(eStatus);
1212     }
1213 
1214     MOS_FreeMemory(compressedHdr);
1215     return eStatus;
1216 }
1217 
1218 }  // namespace encode
1219