1 /*
2 * Copyright (c) 2017-2018, 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     codechal_encode_hevc_base.cpp
24 //! \brief    Defines base class for HEVC encoder.
25 //!
26 
27 #include "codechal_encode_hevc_base.h"
28 #include "codechal_vdenc_hevc.h"
29 #include "codechal_encode_hevc.h"
30 #include "encode_hevc_header_packer.h"
31 #if USE_CODECHAL_DEBUG_TOOL
32 #include "codechal_debug.h"
33 #endif
34 
35 const uint8_t CodechalEncodeHevcBase::TransformSkipCoeffsTable[4][2][2][2][2] =
36 {
37     { { { { 42, 37 },{ 32, 40 } },{ { 40, 40 },{ 32, 45 } } },{ { { 29, 48 },{ 26, 53 } },{ { 26, 56 },{ 24, 62 } } } },
38     { { { { 42, 40 },{ 32, 45 } },{ { 40, 46 },{ 32, 48 } } },{ { { 26, 53 },{ 24, 58 } },{ { 32, 53 },{ 26, 64 } } } },
39     { { { { 38, 42 },{ 32, 51 } },{ { 43, 43 },{ 35, 46 } } },{ { { 26, 56 },{ 24, 64 } },{ { 35, 50 },{ 32, 57 } } } },
40     { { { { 35, 46 },{ 32, 52 } },{ { 51, 42 },{ 38, 53 } } },{ { { 29, 56 },{ 29, 70 } },{ { 38, 47 },{ 37, 64 } } } },
41 };
42 
43 const uint16_t CodechalEncodeHevcBase::TransformSkipLambdaTable[QP_NUM] =
44 {
45     149, 149, 149, 149, 149, 149, 149, 149,
46     149, 149, 149, 149, 149, 149, 149, 149,
47     149, 149, 149, 149, 149, 149, 149, 149,
48     149, 162, 174, 186, 199, 211, 224, 236,
49     249, 261, 273, 286, 298, 298, 298, 298,
50     298, 298, 298, 298, 298, 298, 298, 298,
51     298, 298, 298, 298
52 };
53 
InitMmcState()54 MOS_STATUS CodechalEncodeHevcBase::InitMmcState()
55 {
56 #ifdef _MMC_SUPPORTED
57     m_mmcState = MOS_New(CodechalMmcEncodeHevc, m_hwInterface, this);
58     CODECHAL_ENCODE_CHK_NULL_RETURN(m_mmcState);
59 #endif
60     return MOS_STATUS_SUCCESS;
61 }
62 
Initialize(CodechalSetting * settings)63 MOS_STATUS CodechalEncodeHevcBase::Initialize(CodechalSetting * settings)
64 {
65     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
66 
67     CODECHAL_ENCODE_FUNCTION_ENTER;
68 
69     CODECHAL_ENCODE_CHK_NULL_RETURN(settings);
70 
71 #ifndef _FULL_OPEN_SOURCE
72     // for HEVC: the Ds+Copy kernel is by default used to do CSC and copy non-aligned surface
73     CODECHAL_ENCODE_CHK_NULL_RETURN(m_cscDsState);
74     m_cscDsState->EnableCopy();
75     m_cscDsState->EnableColor();
76 #endif
77     m_mfeEnabled = settings->isMfeEnabled;
78 
79     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::Initialize(settings));
80 
81     CODECHAL_ENCODE_CHK_STATUS_RETURN(InitMmcState());
82 
83     m_is10BitHevc  = (settings->lumaChromaDepth & CODECHAL_LUMA_CHROMA_DEPTH_10_BITS) ? true : false;
84     m_chromaFormat = settings->chromaFormat;
85     m_bitDepth     = (settings->lumaChromaDepth & CODECHAL_LUMA_CHROMA_DEPTH_8_BITS) ? 8 : ((settings->lumaChromaDepth & CODECHAL_LUMA_CHROMA_DEPTH_10_BITS) ? 10 : 12);
86     m_frameNum = 0;
87 
88     const uint32_t picWidthInLCU = MOS_ROUNDUP_DIVIDE(m_frameWidth, CODECHAL_HEVC_MIN_LCU_SIZE);        //assume smallest LCU to get max width
89     const uint32_t picHeightInLCU = MOS_ROUNDUP_DIVIDE(m_frameHeight, CODECHAL_HEVC_MIN_LCU_SIZE);      //assume smallest LCU to get max height                                                                                            // MaxNumLcu is when LCU size is min lcu size(16)
90     const uint32_t maxNumLCUs = picWidthInLCU *  picHeightInLCU;
91     m_mvOffset = MOS_ALIGN_CEIL((maxNumLCUs * (m_hcpInterface->GetHcpPakObjSize()) * sizeof(uint32_t)), CODECHAL_PAGE_SIZE);
92 
93     // MaxNumCuRecords is when LCU size is max lcu size(64)
94     const uint32_t maxNumCuRecords = MOS_ROUNDUP_DIVIDE(m_frameWidth, MAX_LCU_SIZE) *
95         MOS_ROUNDUP_DIVIDE(m_frameHeight, MAX_LCU_SIZE) * 64;
96     m_mbCodeSize =
97         m_mvOffset + MOS_ALIGN_CEIL((maxNumCuRecords * m_hcpInterface->GetHevcEncCuRecordSize()), CODECHAL_PAGE_SIZE);
98 
99     m_widthAlignedMaxLcu  = MOS_ALIGN_CEIL(m_frameWidth, MAX_LCU_SIZE);
100     m_heightAlignedMaxLcu = MOS_ALIGN_CEIL(m_frameHeight, MAX_LCU_SIZE);
101 
102     m_hevcBrcPakStatisticsSize = HEVC_BRC_PAK_STATISTCS_SIZE; // size for sturcture: CODECHAL_ENCODE_HEVC_PAK_STATS_BUFFER
103     m_sizeOfHcpPakFrameStats   = 8 * CODECHAL_CACHELINE_SIZE;
104 
105     // Initialize kernel State
106     CODECHAL_ENCODE_CHK_STATUS_RETURN(InitKernelState());
107 
108     // Get max binding table count
109     m_maxBtCount = GetMaxBtCount();
110 
111     // Picture Level Commands
112     CODECHAL_ENCODE_CHK_STATUS_RETURN(CalculatePictureStateCommandSize());
113 
114     // Slice Level Commands
115     CODECHAL_ENCODE_CHK_STATUS_RETURN(
116         m_hwInterface->GetHxxPrimitiveCommandSize(
117             CODECHAL_ENCODE_MODE_HEVC,
118             &m_defaultSliceStatesSize,
119             &m_defaultSlicePatchListSize,
120             m_singleTaskPhaseSupported));
121 
122 #if (_DEBUG || _RELEASE_INTERNAL)
123     MOS_USER_FEATURE_VALUE_DATA userFeatureData;
124     MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
125     MOS_UserFeature_ReadValue_ID(
126         nullptr,
127         __MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_IFRAME_RDOQ_ENABLE_ID,
128         &userFeatureData,
129         m_osInterface->pOsContext);
130     m_hevcIFrameRdoqEnabled = userFeatureData.i32Data ? true : false;
131 
132     MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
133     MOS_UserFeature_ReadValue_ID(
134         nullptr,
135         __MEDIA_USER_FEATURE_VALUE_CODECHAL_RDOQ_INTRA_TU_OVERRIDE_ID,
136         &userFeatureData,
137         m_osInterface->pOsContext);
138     m_rdoqIntraTuOverride = (uint32_t)userFeatureData.u32Data;
139 
140     MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
141     MOS_UserFeature_ReadValue_ID(
142         nullptr,
143         __MEDIA_USER_FEATURE_VALUE_CODECHAL_RDOQ_INTRA_TU_DISABLE_ID,
144         &userFeatureData,
145         m_osInterface->pOsContext);
146     m_rdoqIntraTuDisableOverride = (uint32_t)userFeatureData.u32Data;
147 
148     MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
149     MOS_UserFeature_ReadValue_ID(
150         nullptr,
151         __MEDIA_USER_FEATURE_VALUE_CODECHAL_RDOQ_INTRA_TU_THRESHOLD_ID,
152         &userFeatureData,
153         m_osInterface->pOsContext);
154     m_rdoqIntraTuThresholdOverride = (uint32_t)userFeatureData.u32Data;
155 #endif
156     return eStatus;
157 }
158 
AllocatePakResources()159 MOS_STATUS CodechalEncodeHevcBase::AllocatePakResources()
160 {
161     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
162 
163     CODECHAL_ENCODE_FUNCTION_ENTER;
164 
165     const uint32_t minLcuSize = 16;
166     const uint32_t picWidthInMinLCU = MOS_ROUNDUP_DIVIDE(m_frameWidth, minLcuSize);        //assume smallest LCU to get max width
167     const uint32_t picHeightInMinLCU = MOS_ROUNDUP_DIVIDE(m_frameHeight, minLcuSize);      //assume smallest LCU to get max height
168 
169     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
170     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
171     allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
172     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
173     allocParamsForBufferLinear.Format = Format_Buffer;
174 
175     // Deblocking Filter Row Store Scratch data surface
176     const uint32_t formatDenom = 2;
177     uint32_t       formatMultiFactor = m_chromaFormat == HCP_CHROMA_FORMAT_YUV444 ? 3 : 2;
178     formatMultiFactor *= m_is10BitHevc ? 2 : 1;
179 
180     uint32_t size = ((m_frameWidth + 31) & 0xFFFFFFE0) >> 3;
181     size = MOS_ALIGN_CEIL(MOS_ROUNDUP_DIVIDE(size * formatMultiFactor, formatDenom), 4);
182     size *= CODECHAL_CACHELINE_SIZE;
183     allocParamsForBufferLinear.dwBytes = size;
184     allocParamsForBufferLinear.pBufName = "DeblockingScratchBuffer";
185 
186     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
187         m_osInterface,
188         &allocParamsForBufferLinear,
189         &m_resDeblockingFilterRowStoreScratchBuffer);
190 
191     if (eStatus != MOS_STATUS_SUCCESS)
192     {
193         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Deblocking Filter Row Store Scratch Buffer.");
194         return eStatus;
195     }
196 
197     // Deblocking Filter Tile Row Store Scratch data surface
198     allocParamsForBufferLinear.dwBytes = size;
199     allocParamsForBufferLinear.pBufName = "DeblockingTileScratchBuffer";
200 
201     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
202         m_osInterface,
203         &allocParamsForBufferLinear,
204         &m_resDeblockingFilterTileRowStoreScratchBuffer);
205 
206     if (eStatus != MOS_STATUS_SUCCESS)
207     {
208         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Deblocking Filter Tile Row Store Scratch Buffer.");
209         return eStatus;
210     }
211 
212     // Deblocking Filter Column Row Store Scratch data surface
213     size = ((m_frameHeight + picHeightInMinLCU * 6 + 31) & 0xFFFFFFE0) >> 3;
214     size = MOS_ALIGN_CEIL(MOS_ROUNDUP_DIVIDE(size * formatMultiFactor, formatDenom), 4);
215     size *= CODECHAL_CACHELINE_SIZE;
216     allocParamsForBufferLinear.dwBytes = size;
217     allocParamsForBufferLinear.pBufName = "DeblockingColumnScratchBuffer";
218 
219     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
220         m_osInterface,
221         &allocParamsForBufferLinear,
222         &m_resDeblockingFilterColumnRowStoreScratchBuffer);
223 
224     if (eStatus != MOS_STATUS_SUCCESS)
225     {
226         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Deblocking Filter Column Row Store Scratch Buffer.");
227         return eStatus;
228     }
229 
230     // Metadata Line buffer
231     size = MOS_MAX(
232         MOS_ALIGN_CEIL((m_frameWidth + picWidthInMinLCU * 8 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE,                       // intra-slice
233         MOS_ALIGN_CEIL((((m_frameWidth + 15) >> 4) * 188 + picWidthInMinLCU * 9 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE    // inter-slice
234     );
235     allocParamsForBufferLinear.dwBytes = size;
236     allocParamsForBufferLinear.pBufName = "MetadataLineBuffer";
237 
238     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
239         m_osInterface,
240         &allocParamsForBufferLinear,
241         &m_resMetadataLineBuffer);
242 
243     if (eStatus != MOS_STATUS_SUCCESS)
244     {
245         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Metadata Line Buffer.");
246         return eStatus;
247     }
248 
249     // Metadata Tile Line buffer
250     size = MOS_MAX(
251         MOS_ALIGN_CEIL((m_frameWidth + picWidthInMinLCU * 8 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE,                  // intra-slice
252         MOS_ALIGN_CEIL((((m_frameWidth + 15) >> 4) * 172 + picWidthInMinLCU * 9 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE   // inter-slice
253     );
254     allocParamsForBufferLinear.dwBytes = size;
255     allocParamsForBufferLinear.pBufName = "MetadataTileLineBuffer";
256 
257     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
258         m_osInterface,
259         &allocParamsForBufferLinear,
260         &m_resMetadataTileLineBuffer);
261 
262     if (eStatus != MOS_STATUS_SUCCESS)
263     {
264         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Metadata Tile Line Buffer.");
265         return eStatus;
266     }
267 
268     // Metadata Tile Column buffer
269     size = MOS_MAX(
270         MOS_ALIGN_CEIL((m_frameHeight + picHeightInMinLCU * 8 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE,                    // intra-slice
271         MOS_ALIGN_CEIL((((m_frameHeight + 15) >> 4) * 172 + picHeightInMinLCU * 9 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE // inter-slice
272     );
273     allocParamsForBufferLinear.dwBytes = size;
274     allocParamsForBufferLinear.pBufName = "MetadataTileColumnBuffer";
275 
276     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
277         m_osInterface,
278         &allocParamsForBufferLinear,
279         &m_resMetadataTileColumnBuffer);
280 
281     if (eStatus != MOS_STATUS_SUCCESS)
282     {
283         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Metadata Tile Column Buffer.");
284         return eStatus;
285     }
286 
287     MHW_VDBOX_HCP_BUFFER_SIZE_PARAMS hcpBufSizeParam;
288     MOS_ZeroMemory(&hcpBufSizeParam, sizeof(hcpBufSizeParam));
289     hcpBufSizeParam.ucMaxBitDepth  = m_bitDepth;
290     hcpBufSizeParam.ucChromaFormat = m_chromaFormat;
291 
292     hcpBufSizeParam.dwCtbLog2SizeY = 6; // assume Max LCU size
293     hcpBufSizeParam.dwPicWidth = MOS_ALIGN_CEIL(m_frameWidth, MAX_LCU_SIZE);
294     hcpBufSizeParam.dwPicHeight = MOS_ALIGN_CEIL(m_frameHeight, MAX_LCU_SIZE);
295     // SAO Line buffer
296     eStatus = (MOS_STATUS)m_hcpInterface->GetHevcBufferSize(
297         MHW_VDBOX_HCP_INTERNAL_BUFFER_SAO_LINE,
298         &hcpBufSizeParam);
299 
300     if (eStatus != MOS_STATUS_SUCCESS)
301     {
302         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to get the size for SAO Line Buffer.");
303         return eStatus;
304     }
305 
306     allocParamsForBufferLinear.dwBytes = hcpBufSizeParam.dwBufferSize;
307     allocParamsForBufferLinear.pBufName = "SaoLineBuffer";
308     eStatus                             = (MOS_STATUS)m_osInterface->pfnAllocateResource(
309         m_osInterface,
310         &allocParamsForBufferLinear,
311         &m_resSaoLineBuffer);
312 
313     if (eStatus != MOS_STATUS_SUCCESS)
314     {
315         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate SAO Line Buffer.");
316         return eStatus;
317     }
318 
319     // SAO Tile Line buffer
320     eStatus = (MOS_STATUS)m_hcpInterface->GetHevcBufferSize(
321         MHW_VDBOX_HCP_INTERNAL_BUFFER_SAO_TILE_LINE,
322         &hcpBufSizeParam);
323 
324     if (eStatus != MOS_STATUS_SUCCESS)
325     {
326         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to get the size for SAO Tile Line Buffer.");
327         return eStatus;
328     }
329 
330     allocParamsForBufferLinear.dwBytes = hcpBufSizeParam.dwBufferSize;
331     allocParamsForBufferLinear.pBufName = "SaoTileLineBuffer";
332 
333     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
334         m_osInterface,
335         &allocParamsForBufferLinear,
336         &m_resSaoTileLineBuffer);
337 
338     if (eStatus != MOS_STATUS_SUCCESS)
339     {
340         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate SAO Tile Line Buffer.");
341         return eStatus;
342     }
343 
344     // SAO Tile Column buffer
345     eStatus = (MOS_STATUS)m_hcpInterface->GetHevcBufferSize(
346         MHW_VDBOX_HCP_INTERNAL_BUFFER_SAO_TILE_COL,
347         &hcpBufSizeParam);
348 
349     if (eStatus != MOS_STATUS_SUCCESS)
350     {
351         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to get the size for SAO Tile Column Buffer.");
352         return eStatus;
353     }
354 
355     allocParamsForBufferLinear.dwBytes = hcpBufSizeParam.dwBufferSize;
356     allocParamsForBufferLinear.pBufName = "SaoTileColumnBuffer";
357 
358     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
359         m_osInterface,
360         &allocParamsForBufferLinear,
361         &m_resSaoTileColumnBuffer);
362 
363     if (eStatus != MOS_STATUS_SUCCESS)
364     {
365         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate SAO Tile Column Buffer.");
366         return eStatus;
367     }
368 
369     // Lcu ILDB StreamOut buffer
370     size = 1000000;
371     allocParamsForBufferLinear.dwBytes = size;
372     allocParamsForBufferLinear.pBufName = "LcuILDBStreamOutBuffer";
373 
374     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
375         m_osInterface,
376         &allocParamsForBufferLinear,
377         &m_resLcuIldbStreamOutBuffer);
378 
379     if (eStatus != MOS_STATUS_SUCCESS)
380     {
381         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate LCU ILDB StreamOut Buffer.");
382         return eStatus;
383     }
384 
385     // Lcu Base Address buffer
386     // HEVC Encoder Mode: Slice size is written to this buffer when slice size conformance is enabled.
387     // 1 CL (= 16 DWs = 64 bytes) per slice * Maximum number of dynamic slice = 600
388     // Note that simulation is assigning much larger space for this.
389     allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(CODECHAL_HEVC_MAX_NUM_SLICES_LVL_6 * CODECHAL_CACHELINE_SIZE, CODECHAL_PAGE_SIZE);
390     allocParamsForBufferLinear.pBufName = "LcuBaseAddressBuffer";
391 
392     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
393         m_osInterface,
394         &allocParamsForBufferLinear,
395         &m_resLcuBaseAddressBuffer);
396 
397     if (eStatus != MOS_STATUS_SUCCESS)
398     {
399         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate LCU Base Address Buffer.");
400         return eStatus;
401     }
402 
403     uint32_t mvt_size = MOS_ALIGN_CEIL(((m_frameWidth + 63) >> 6)*((m_frameHeight + 15) >> 4), 2) * CODECHAL_CACHELINE_SIZE;
404     uint32_t mvtb_size = MOS_ALIGN_CEIL(((m_frameWidth + 31) >> 5)*((m_frameHeight + 31) >> 5), 2) * CODECHAL_CACHELINE_SIZE;
405     m_sizeOfMvTemporalBuffer = MOS_MAX(mvt_size, mvtb_size);
406 
407     // SAO StreamOut buffer
408     size = MOS_ALIGN_CEIL(picWidthInMinLCU * picHeightInMinLCU * 16, CODECHAL_CACHELINE_SIZE);  // 16 bytes per LCU
409     allocParamsForBufferLinear.dwBytes = size;
410     allocParamsForBufferLinear.pBufName = "SaoStreamOutBuffer";
411 
412     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
413         m_osInterface,
414         &allocParamsForBufferLinear,
415         &m_resSaoStreamOutBuffer);
416 
417     if (eStatus != MOS_STATUS_SUCCESS)
418     {
419         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate SAO StreamOut Buffer.");
420         return eStatus;
421     }
422 
423     return eStatus;
424 }
425 
AllocateResources()426 MOS_STATUS CodechalEncodeHevcBase::AllocateResources()
427 {
428     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
429 
430     CODECHAL_ENCODE_FUNCTION_ENTER;
431 
432     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::AllocateResources());
433 
434     // Allocate Ref Lists
435     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalAllocateDataList(
436         m_refList,
437         CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC));
438 
439     // Create the sync objects which will be used by each reference frame
440     for (uint32_t i = 0; i < CODECHAL_GET_ARRAY_LENGTH(m_refSync); i++)
441     {
442         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(m_osInterface, &m_refSync[i].resSyncObject));
443         m_refSync[i].bInUsed = false;
444     }
445 
446     CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(AllocatePakResources(), "Failed to allocate PAK resources.");
447 
448     if (m_encEnabled)
449     {
450         CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(AllocateEncResources(), "Failed to allocate ENC resources.");
451 
452         CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(AllocateBrcResources(), "Failed to allocate BRC resources.");
453     }
454 
455     CODECHAL_ENCODE_CHK_STATUS_RETURN(InitSurfaceInfoTable());
456     CreateMhwParams();
457 
458     return eStatus;
459 }
460 
AllocateBuffer(PCODECHAL_ENCODE_BUFFER buffer,uint32_t size,const char * name,int32_t dwMemType)461 MOS_STATUS CodechalEncodeHevcBase::AllocateBuffer(
462     PCODECHAL_ENCODE_BUFFER buffer,
463     uint32_t size,
464     const char* name,
465     int32_t dwMemType)
466 {
467     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
468 
469     CODECHAL_ENCODE_FUNCTION_ENTER;
470 
471     CODECHAL_ENCODE_CHK_NULL_RETURN(buffer);
472 
473     MOS_ALLOC_GFXRES_PARAMS allocParams;
474     MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));
475     allocParams.Type = MOS_GFXRES_BUFFER;
476     allocParams.TileType = MOS_TILE_LINEAR;
477     allocParams.Format = Format_Buffer;
478     allocParams.dwBytes = size;
479     allocParams.pBufName = name;
480     allocParams.dwMemType = dwMemType;
481     buffer->dwSize = size;
482 
483     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
484         m_osInterface,
485         &allocParams,
486         &buffer->sResource);
487 
488     if (eStatus != MOS_STATUS_SUCCESS)
489     {
490         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate %s.", name);
491         return eStatus;
492     }
493 
494     MOS_LOCK_PARAMS lockFlags;
495     MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
496     lockFlags.WriteOnly = 1;
497 
498     uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
499         m_osInterface,
500         &buffer->sResource,
501         &lockFlags);
502     CODECHAL_ENCODE_CHK_NULL_RETURN(data);
503 
504     MOS_ZeroMemory(data, size);
505 
506     m_osInterface->pfnUnlockResource(
507         m_osInterface,
508         &buffer->sResource);
509 
510     return eStatus;
511 }
512 
AllocateBuffer2D(PMOS_SURFACE surface,uint32_t width,uint32_t height,const char * name,MOS_TILE_TYPE tileType,int32_t dwMemType)513 MOS_STATUS CodechalEncodeHevcBase::AllocateBuffer2D(
514     PMOS_SURFACE surface,
515     uint32_t width,
516     uint32_t height,
517     const char* name,
518     MOS_TILE_TYPE tileType,
519     int32_t dwMemType)
520 {
521     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
522 
523     CODECHAL_ENCODE_FUNCTION_ENTER;
524 
525     CODECHAL_ENCODE_CHK_NULL_RETURN(surface);
526 
527     MOS_ZeroMemory(surface, sizeof(*surface));
528 
529     surface->TileType = tileType;
530     surface->bArraySpacing = true;
531     surface->Format = Format_Buffer_2D;
532     surface->dwWidth = MOS_ALIGN_CEIL(width, 64);
533     surface->dwHeight = height;
534     surface->dwPitch = surface->dwWidth;
535 
536     MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
537     MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
538     allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
539     allocParamsForBuffer2D.TileType = surface->TileType;
540     allocParamsForBuffer2D.Format = surface->Format;
541     allocParamsForBuffer2D.dwWidth = surface->dwWidth;
542     allocParamsForBuffer2D.dwHeight = surface->dwHeight;
543     allocParamsForBuffer2D.pBufName = name;
544     allocParamsForBuffer2D.dwMemType = dwMemType;
545 
546     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
547         m_osInterface,
548         &allocParamsForBuffer2D,
549         &surface->OsResource);
550 
551     if (eStatus != MOS_STATUS_SUCCESS)
552     {
553         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate %s.", name);
554         return eStatus;
555     }
556 
557     MOS_LOCK_PARAMS lockFlagsWriteOnly;
558     MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
559     lockFlagsWriteOnly.WriteOnly = true;
560 
561     uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
562         m_osInterface,
563         &(surface->OsResource),
564         &lockFlagsWriteOnly);
565 
566     if (data == nullptr)
567     {
568         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock 2D Surface.");
569         eStatus = MOS_STATUS_UNKNOWN;
570         return eStatus;
571     }
572 
573     MOS_ZeroMemory(data, surface->dwWidth * surface->dwHeight);
574 
575     m_osInterface->pfnUnlockResource(m_osInterface, &(surface->OsResource));
576 
577     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
578         m_osInterface,
579         surface));
580 
581     return eStatus;
582 }
583 
AllocateSurface(PMOS_SURFACE surface,uint32_t width,uint32_t height,const char * name,int32_t dwMemType)584 MOS_STATUS CodechalEncodeHevcBase::AllocateSurface(
585     PMOS_SURFACE surface,
586     uint32_t width,
587     uint32_t height,
588     const char* name,
589     int32_t dwMemType)
590 {
591     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
592 
593     CODECHAL_ENCODE_FUNCTION_ENTER;
594 
595     CODECHAL_ENCODE_CHK_NULL_RETURN(surface);
596 
597     MOS_ALLOC_GFXRES_PARAMS allocParams;
598     MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));
599     allocParams.Type = MOS_GFXRES_2D;
600     allocParams.TileType = MOS_TILE_Y;
601     allocParams.Format = Format_NV12;
602     allocParams.dwWidth = width;
603     allocParams.dwHeight = height;
604     allocParams.pBufName = name;
605     allocParams.dwMemType = dwMemType;
606 
607     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
608         m_osInterface,
609         &allocParams,
610         &surface->OsResource);
611 
612     if (eStatus != MOS_STATUS_SUCCESS)
613     {
614         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate %s.", name);
615         return eStatus;
616     }
617 
618     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
619         m_osInterface,
620         surface));
621 
622     return eStatus;
623 }
624 
AllocateBatchBufferForPakSlices(uint32_t numSlices,uint8_t numPakPasses)625 MOS_STATUS CodechalEncodeHevcBase::AllocateBatchBufferForPakSlices(
626     uint32_t numSlices,
627     uint8_t  numPakPasses)
628 {
629     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
630 
631     CODECHAL_ENCODE_FUNCTION_ENTER;
632 
633     MOS_ZeroMemory(
634         &m_batchBufferForPakSlices[m_currPakSliceIdx],
635         sizeof(MHW_BATCH_BUFFER));
636 
637     // Get the slice size
638     uint32_t size = (numPakPasses + 1) * numSlices * m_sliceStatesSize;
639 
640     m_batchBufferForPakSlices[m_currPakSliceIdx].bSecondLevel = true;
641     CODECHAL_ENCODE_CHK_STATUS_RETURN(Mhw_AllocateBb(
642         m_osInterface,
643         &m_batchBufferForPakSlices[m_currPakSliceIdx],
644         nullptr,
645         size));
646 
647     MOS_LOCK_PARAMS lockFlags;
648     MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
649     lockFlags.WriteOnly = 1;
650     uint8_t *data       = (uint8_t *)m_osInterface->pfnLockResource(
651         m_osInterface,
652         &m_batchBufferForPakSlices[m_currPakSliceIdx].OsResource,
653         &lockFlags);
654 
655     if (data == nullptr)
656     {
657         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to lock batch buffer for PAK slices.");
658         eStatus = MOS_STATUS_UNKNOWN;
659         return eStatus;
660     }
661 
662     MOS_ZeroMemory(data, size);
663     m_osInterface->pfnUnlockResource(
664         m_osInterface,
665         &m_batchBufferForPakSlices[m_currPakSliceIdx].OsResource);
666 
667     return eStatus;
668 }
669 
ReadSseStatistics(PMOS_COMMAND_BUFFER cmdBuffer)670 MOS_STATUS CodechalEncodeHevcBase::ReadSseStatistics(PMOS_COMMAND_BUFFER cmdBuffer)
671 {
672     CODECHAL_ENCODE_FUNCTION_ENTER;
673 
674     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
675 
676     // encodeStatus is offset by 2 DWs in the resource
677     uint32_t sseOffsetinBytes = (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize) + sizeof(uint32_t) * 2 + m_encodeStatusBuf.dwSumSquareErrorOffset;
678     for (auto i = 0; i < 6; i++)    // 64 bit SSE values for luma/ chroma channels need to be copied
679     {
680         MHW_MI_COPY_MEM_MEM_PARAMS miCpyMemMemParams;
681         MOS_ZeroMemory(&miCpyMemMemParams, sizeof(miCpyMemMemParams));
682         miCpyMemMemParams.presSrc     = &m_resFrameStatStreamOutBuffer;
683         miCpyMemMemParams.dwSrcOffset = (HEVC_PAK_STATISTICS_SSE_OFFSET + i) * sizeof(uint32_t);    // SSE luma offset is located at DW32 in Frame statistics, followed by chroma
684         miCpyMemMemParams.presDst = &m_encodeStatusBuf.resStatusBuffer;
685         miCpyMemMemParams.dwDstOffset = sseOffsetinBytes + i * sizeof(uint32_t);
686         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiCopyMemMemCmd(cmdBuffer, &miCpyMemMemParams));
687     }
688     return eStatus;
689 }
690 
CalculatePSNR(EncodeStatus * encodeStatus,EncodeStatusReport * encodeStatusReport)691 MOS_STATUS CodechalEncodeHevcBase::CalculatePSNR(
692     EncodeStatus       *encodeStatus,
693     EncodeStatusReport *encodeStatusReport)
694 {
695     CODECHAL_ENCODE_FUNCTION_ENTER;
696 
697     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
698 
699     CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatus);
700     CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatusReport);
701     uint32_t numLumaPixels = 0, numPixelsPerChromaChannel = 0;
702 
703     numLumaPixels = m_frameHeight * m_frameWidth;
704     switch (m_hevcSeqParams->chroma_format_idc)
705     {
706     case HCP_CHROMA_FORMAT_MONOCHROME:
707         numPixelsPerChromaChannel = 0;
708         break;
709     case HCP_CHROMA_FORMAT_YUV420:
710         numPixelsPerChromaChannel = numLumaPixels / 4;
711         break;
712     case HCP_CHROMA_FORMAT_YUV422:
713         numPixelsPerChromaChannel = numLumaPixels / 2;
714         break;
715     case HCP_CHROMA_FORMAT_YUV444:
716         numPixelsPerChromaChannel = numLumaPixels;
717         break;
718     default:
719         numPixelsPerChromaChannel = numLumaPixels / 2;
720         break;
721     }
722 
723     double squarePeakPixelValue = pow((1 << (m_hevcSeqParams->bit_depth_luma_minus8 + 8)) - 1, 2);
724 
725     for (auto i = 0; i < 3; i++)
726     {
727         uint32_t numPixels = i ? numPixelsPerChromaChannel : numLumaPixels;
728 
729         if (m_hevcSeqParams->bit_depth_luma_minus8 == 0)
730         {
731             //8bit pixel data is represented in 10bit format in HW. so SSE should right shift by 4.
732             encodeStatus->sumSquareError[i] >>= 4;
733         }
734         encodeStatusReport->PSNRx100[i] = (uint16_t) CodecHal_Clip3(0, 10000,
735             (uint16_t) (encodeStatus->sumSquareError[i] ? 1000 * log10(squarePeakPixelValue * numPixels / encodeStatus->sumSquareError[i]) : -1));
736 
737         CODECHAL_ENCODE_VERBOSEMESSAGE("PSNRx100[%d]:%d.\n", i, encodeStatusReport->PSNRx100[i]);
738     }
739 
740     return eStatus;
741 }
742 
ReleaseBatchBufferForPakSlices(uint32_t index)743 MOS_STATUS CodechalEncodeHevcBase::ReleaseBatchBufferForPakSlices(uint32_t index)
744 {
745     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
746 
747     if (m_batchBufferForPakSlices[index].iSize)
748     {
749         Mhw_FreeBb(m_osInterface, &m_batchBufferForPakSlices[index], nullptr);
750         m_batchBufferForPakSlices[index].iSize = 0;
751     }
752 
753     return eStatus;
754 }
755 
FreePakResources()756 MOS_STATUS CodechalEncodeHevcBase::FreePakResources()
757 {
758     CODECHAL_ENCODE_FUNCTION_ENTER;
759 
760     for (auto i = 0; i < CODECHAL_HEVC_NUM_PAK_SLICE_BATCH_BUFFERS; i++)
761     {
762         ReleaseBatchBufferForPakSlices(i);
763     }
764 
765     m_osInterface->pfnFreeResource(m_osInterface, &m_resDeblockingFilterRowStoreScratchBuffer);
766     m_osInterface->pfnFreeResource(m_osInterface, &m_resDeblockingFilterTileRowStoreScratchBuffer);
767     m_osInterface->pfnFreeResource(m_osInterface, &m_resDeblockingFilterColumnRowStoreScratchBuffer);
768     m_osInterface->pfnFreeResource(m_osInterface, &m_resMetadataLineBuffer);
769     m_osInterface->pfnFreeResource(m_osInterface, &m_resMetadataTileLineBuffer);
770     m_osInterface->pfnFreeResource(m_osInterface, &m_resMetadataTileColumnBuffer);
771     m_osInterface->pfnFreeResource(m_osInterface, &m_resSaoLineBuffer);
772     m_osInterface->pfnFreeResource(m_osInterface, &m_resSaoTileLineBuffer);
773     m_osInterface->pfnFreeResource(m_osInterface, &m_resSaoTileColumnBuffer);
774     m_osInterface->pfnFreeResource(m_osInterface, &m_resLcuIldbStreamOutBuffer);
775     m_osInterface->pfnFreeResource(m_osInterface, &m_resLcuBaseAddressBuffer);
776     m_osInterface->pfnFreeResource(m_osInterface, &m_resSaoStreamOutBuffer);
777 
778     return MOS_STATUS_SUCCESS;
779 }
780 
FreeResources()781 void CodechalEncodeHevcBase::FreeResources()
782 {
783     CODECHAL_ENCODE_FUNCTION_ENTER;
784 
785     CodechalEncoderState::FreeResources();
786 
787     FreeEncResources();
788     FreeBrcResources();
789     FreePakResources();
790 
791     // Release Ref Lists
792     CodecHalFreeDataList(m_refList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC);
793 
794     for (uint32_t i = 0; i < CODECHAL_GET_ARRAY_LENGTH(m_refSync); i++)
795     {
796         m_osInterface->pfnDestroySyncResource(m_osInterface, &m_refSync[i].resSyncObject);
797     }
798 
799     if (m_sliceStateParams)
800     {
801         MOS_Delete(m_sliceStateParams);
802         m_sliceStateParams = nullptr;
803     }
804     if (m_pipeModeSelectParams)
805     {
806         MOS_Delete(m_pipeModeSelectParams);
807         m_pipeModeSelectParams = nullptr;
808     }
809     if (m_pipeBufAddrParams)
810     {
811         MOS_Delete(m_pipeBufAddrParams);
812         m_pipeBufAddrParams = nullptr;
813     }
814 }
815 
SetSequenceStructs()816 MOS_STATUS CodechalEncodeHevcBase::SetSequenceStructs()
817 {
818     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
819 
820     CODECHAL_ENCODE_FUNCTION_ENTER;
821 
822     uint32_t frameWidth = (m_hevcSeqParams->wFrameWidthInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3);
823 
824     uint32_t frameHeight = (m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3);
825 
826     // check if there is a dynamic resolution change
827     if ((m_oriFrameHeight && (m_oriFrameHeight != frameHeight)) ||
828         (m_oriFrameWidth && (m_oriFrameWidth != frameWidth)))
829     {
830         if (frameHeight > m_createHeight || frameWidth > m_createWidth)
831         {
832             CODECHAL_ENCODE_ASSERTMESSAGE("Resolution reset from lower resolution to higher resolution not supported if it is higher than the resolution of first frame.%d, %d %d, %d", m_createWidth, m_createHeight, frameWidth, frameHeight);
833             eStatus = MOS_STATUS_INVALID_PARAMETER;
834             return eStatus;
835         }
836         m_resolutionChanged = true;
837         m_brcInit           = true;
838     }
839     else
840     {
841         m_resolutionChanged = false;
842     }
843 
844     // setup internal parameters
845     m_oriFrameWidth = m_frameWidth = frameWidth;
846     m_oriFrameHeight = m_frameHeight = frameHeight;
847 
848     m_picWidthInMb = (uint16_t)CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_oriFrameWidth);
849     m_picHeightInMb = (uint16_t)CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_oriFrameHeight);
850 
851     if (m_resolutionChanged)
852     {
853         m_widthAlignedMaxLcu  = MOS_ALIGN_CEIL(m_frameWidth, MAX_LCU_SIZE);
854         m_heightAlignedMaxLcu = MOS_ALIGN_CEIL(m_frameHeight, MAX_LCU_SIZE);
855     }
856 
857     // Get row store cache params: as all the needed information is got here
858     if (m_hcpInterface->IsRowStoreCachingSupported())
859     {
860         MHW_VDBOX_ROWSTORE_PARAMS rowstoreParams = {};
861         rowstoreParams.Mode = m_mode;
862         rowstoreParams.dwPicWidth = m_frameWidth;
863                 rowstoreParams.ucChromaFormat   = m_chromaFormat;
864                 rowstoreParams.ucBitDepthMinus8 = m_hevcSeqParams->bit_depth_luma_minus8;
865                 rowstoreParams.ucLCUSize        = 1 << (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3);
866                 m_hwInterface->SetRowstoreCachingOffsets(&rowstoreParams);
867     }
868 
869     m_brcEnabled = IsRateControlBrc(m_hevcSeqParams->RateControlMethod);
870 
871     if (m_brcEnabled)
872     {
873         switch (m_hevcSeqParams->MBBRC)
874         {
875         case mbBrcInternal:
876             m_lcuBrcEnabled = (m_hevcSeqParams->TargetUsage == 1);
877             break;
878         case mbBrcDisabled:
879             m_lcuBrcEnabled = false;
880             break;
881         case mbBrcEnabled:
882             m_lcuBrcEnabled = true;
883             break;
884         }
885 
886         if (m_hevcSeqParams->RateControlMethod == RATECONTROL_ICQ  ||
887             m_hevcSeqParams->RateControlMethod == RATECONTROL_QVBR ||
888             m_hevcPicParams->NumROI)
889         {
890             // ICQ or ROI must result in LCU-based BRC to be enabled.
891             m_lcuBrcEnabled = true;
892         }
893     }
894 
895     if (m_hevcSeqParams->RateControlMethod == RATECONTROL_VCM && m_lcuBrcEnabled)
896     {
897         m_lcuBrcEnabled = false;  // when VCM is enabled, only frame-based BRC
898     }
899 
900     if (m_hevcSeqParams->RateControlMethod == RATECONTROL_ICQ || m_hevcSeqParams->RateControlMethod == RATECONTROL_QVBR)
901     {
902         if (m_hevcSeqParams->ICQQualityFactor < CODECHAL_ENCODE_HEVC_MIN_ICQ_QUALITYFACTOR ||
903             m_hevcSeqParams->ICQQualityFactor > CODECHAL_ENCODE_HEVC_MAX_ICQ_QUALITYFACTOR)
904         {
905             CODECHAL_ENCODE_ASSERTMESSAGE("Invalid ICQ Quality Factor input (%d)\n", m_hevcSeqParams->ICQQualityFactor);
906             eStatus = MOS_STATUS_INVALID_PARAMETER;
907             return eStatus;
908         }
909     }
910 
911     m_usAvbrAccuracy    = CODECHAL_ENCODE_HEVC_DEFAULT_AVBR_ACCURACY;
912     m_usAvbrConvergence = CODECHAL_ENCODE_HEVC_DEFAULT_AVBR_CONVERGENCE;
913 
914     // Calculate 4x, 16x, 32x dimensions as applicable
915     CODECHAL_ENCODE_CHK_STATUS_RETURN(CalcScaledDimensions());
916 
917     // It is assumed to be frame-mode always
918     m_frameFieldHeight = m_frameHeight;
919     m_frameFieldHeightInMb = m_picHeightInMb;
920     m_downscaledFrameFieldHeightInMb16x = m_downscaledHeightInMb16x;
921     m_downscaledFrameFieldHeightInMb4x = m_downscaledHeightInMb4x;
922     m_downscaledFrameFieldHeightInMb32x = m_downscaledHeightInMb32x;
923 
924     m_brcReset          = m_hevcSeqParams->bResetBRC;
925     m_roiValueInDeltaQp = m_hevcSeqParams->ROIValueInDeltaQP;
926 
927     uint32_t lcuInRow    = MOS_ALIGN_CEIL(m_frameWidth, (1 << (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3))) >> (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3);
928     uint32_t lcu2MbRatio = (1 << (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3)) / CODECHAL_MACROBLOCK_WIDTH;
929     if (lcuInRow < 1 || lcu2MbRatio < 1)
930     {
931         eStatus = MOS_STATUS_INVALID_PARAMETER;
932         return eStatus;
933     }
934 
935     if (m_brcReset &&
936         (!m_brcEnabled ||
937             m_hevcSeqParams->RateControlMethod == RATECONTROL_ICQ))
938     {
939         CODECHAL_ENCODE_ASSERTMESSAGE("BRC Reset cannot be trigerred in CQP/ICQ modes - invalid BRC parameters.");
940         m_brcReset = false;
941     }
942 
943     if (m_hevcSeqParams->TargetUsage == 0x07 && !m_enable26WalkingPattern)
944     {
945         m_enable26WalkingPattern = true;  // in the performance mode (TU=7), 26z walking pattern is not supported
946     }
947 
948     if (!m_32xMeUserfeatureControl && m_32xMeSupported && m_hevcSeqParams->TargetUsage == 0x07)
949     {
950         m_32xMeSupported = false; // TU7 does not support ultra HME
951     }
952 
953     m_encode4KSequence = ((m_frameWidth * m_frameHeight) >=
954                              (ENCODE_HEVC_4K_PIC_WIDTH * ENCODE_HEVC_4K_PIC_HEIGHT))
955                              ? true
956                              : false;
957 
958     m_encode16KSequence = ((m_frameWidth * m_frameHeight) >=
959                               (ENCODE_HEVC_16K_PIC_WIDTH * ENCODE_HEVC_16K_PIC_HEIGHT))
960                              ? true
961                              : false;
962 
963     // if GOP structure is I-frame only, we use 3 non-ref slots for tracked buffer
964     m_gopIsIdrFrameOnly = (m_hevcSeqParams->GopPicSize == 1);
965 
966     // check output Chroma format
967     m_outputChromaFormat = m_hevcSeqParams->chroma_format_idc;
968 
969     return eStatus;
970 }
971 
SetPictureStructs()972 MOS_STATUS CodechalEncodeHevcBase::SetPictureStructs()
973 {
974     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
975 
976     CODECHAL_ENCODE_FUNCTION_ENTER;
977 
978     for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
979     {
980         m_refIdxMapping[i]  = -1;
981         m_currUsedRefPic[i] = false;
982     }
983 
984     // To obtain current "used" reference frames. The number of current used reference frames cannot be greater than 8
985     auto slcParams = m_hevcSliceParams;
986     for (uint32_t s = 0; s < m_numSlices; s++, slcParams++)
987     {
988         for (auto ll = 0; ll < 2; ll++)
989         {
990             uint32_t numRef = (ll == 0) ? slcParams->num_ref_idx_l0_active_minus1 :
991                 slcParams->num_ref_idx_l1_active_minus1;
992 
993             if (numRef > CODEC_MAX_NUM_REF_FRAME_HEVC)
994             {
995                 CODECHAL_ENCODE_ASSERTMESSAGE("Invalid number of ref frames for l0 %d or l1 %d", slcParams->num_ref_idx_l0_active_minus1, slcParams->num_ref_idx_l1_active_minus1);
996                 eStatus = MOS_STATUS_INVALID_PARAMETER;
997                 return eStatus;
998             }
999             for (uint32_t i = 0; i <= numRef; i++)
1000             {
1001                 if (i >= CODEC_MAX_NUM_REF_FRAME_HEVC)
1002                 {
1003                     return MOS_STATUS_INVALID_PARAMETER;
1004                 }
1005                 CODEC_PICTURE refPic = slcParams->RefPicList[ll][i];
1006                 if (!CodecHal_PictureIsInvalid(refPic) &&
1007                     !CodecHal_PictureIsInvalid(m_hevcPicParams->RefFrameList[refPic.FrameIdx]))
1008                 {
1009                     m_currUsedRefPic[refPic.FrameIdx] = true;
1010                 }
1011             }
1012         }
1013     }
1014 
1015     for (uint8_t i = 0, RefIdx = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
1016     {
1017         if (!m_currUsedRefPic[i])
1018         {
1019             continue;
1020         }
1021 
1022         uint8_t index         = m_hevcPicParams->RefFrameList[i].FrameIdx;
1023         bool duplicatedIdx = false;
1024         for (unsigned char ii = 0; ii < i; ii++)
1025         {
1026             if (m_currUsedRefPic[i] && index == m_hevcPicParams->RefFrameList[ii].FrameIdx)
1027             {
1028                 // We find the same FrameIdx in the ref_frame_list. Multiple reference frames are the same.
1029                 // In other words, RefFrameList[i] and RefFrameList[ii] have the same surface Id
1030                 duplicatedIdx = true;
1031                 m_refIdxMapping[i] = m_refIdxMapping[ii];
1032                 break;
1033             }
1034         }
1035 
1036         if (duplicatedIdx)
1037         {
1038             continue;
1039         }
1040 
1041         if (RefIdx >= CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC)
1042         {
1043             // Total number of distingushing reference frames cannot be geater than 8.
1044             CODECHAL_ENCODE_ASSERT(false);
1045             eStatus = MOS_STATUS_INVALID_PARAMETER;
1046             return eStatus;
1047         }
1048 
1049         // Map reference frame index [0-15] into a set of unique IDs within [0-7]
1050         m_refIdxMapping[i] = RefIdx;
1051         RefIdx++;
1052     }
1053 
1054     if (m_hevcPicParams->CodingType != I_TYPE && m_hevcPicParams->CollocatedRefPicIndex != 0xFF && m_hevcPicParams->CollocatedRefPicIndex < CODEC_MAX_NUM_REF_FRAME_HEVC)
1055     {
1056         uint8_t frameStoreId = (uint8_t)m_refIdxMapping[m_hevcPicParams->CollocatedRefPicIndex];
1057 
1058         if (frameStoreId >= CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC || !m_currUsedRefPic[m_hevcPicParams->CollocatedRefPicIndex])
1059         {
1060             // CollocatedRefPicIndex is wrong in this case for the reference frame is not used be used
1061             eStatus = MOS_STATUS_INVALID_PARAMETER;
1062             return eStatus;
1063         }
1064     }
1065 
1066     if (m_hevcPicParams->QpY > CODECHAL_ENCODE_HEVC_MAX_SLICE_QP)
1067     {
1068         return MOS_STATUS_INVALID_PARAMETER;
1069     }
1070 
1071     if (Mos_ResourceIsNull(&m_reconSurface.OsResource) &&
1072         (!m_hevcPicParams->bUseRawPicForRef || m_codecFunction != CODECHAL_FUNCTION_ENC))
1073     {
1074         return MOS_STATUS_INVALID_PARAMETER;
1075     }
1076 
1077     if (m_hevcSeqParams->scaling_list_enable_flag && !m_hevcPicParams->scaling_list_data_present_flag)
1078     {
1079         CreateDefaultScalingList();
1080     }
1081     else if (!m_hevcSeqParams->scaling_list_enable_flag)
1082     {
1083         CreateFlatScalingList();
1084     }
1085 
1086     unsigned char prevRefIdx = m_currReconstructedPic.FrameIdx;
1087     PCODEC_REF_LIST *refListFull = &m_refList[0];
1088 
1089     // Sync initialize
1090     if ((m_firstFrame) ||
1091         (!m_brcEnabled && m_hevcPicParams->bUseRawPicForRef) ||
1092         (!m_brcEnabled && (m_hevcPicParams->CodingType == I_TYPE)) ||
1093         (!m_brcEnabled && !refListFull[prevRefIdx]->bUsedAsRef))
1094     {
1095         m_waitForPak = false;
1096     }
1097     else
1098     {
1099         m_waitForPak = true;
1100     }
1101 
1102     if (m_brcEnabled || m_hevcPicParams->bUsedAsRef)
1103     {
1104         m_signalEnc = true;
1105     }
1106     else
1107     {
1108         m_signalEnc = false;
1109     }
1110 
1111     m_currEncBbSet = MB_ENC_Frame_BB;
1112     m_lastPicInSeq               = m_hevcPicParams->bLastPicInSeq;
1113     m_lastPicInStream            = m_hevcPicParams->bLastPicInStream;
1114     m_statusReportFeedbackNumber = m_hevcPicParams->StatusReportFeedbackNumber;
1115     m_currOriginalPic            = m_hevcPicParams->CurrOriginalPic;
1116     m_currReconstructedPic       = m_hevcPicParams->CurrReconstructedPic;
1117 
1118     unsigned char currRefIdx                       = m_hevcPicParams->CurrReconstructedPic.FrameIdx;
1119     refListFull[currRefIdx]->sRefReconBuffer = m_reconSurface;
1120     refListFull[currRefIdx]->sRefRawBuffer = m_rawSurface;
1121     refListFull[currRefIdx]->RefPic                = m_hevcPicParams->CurrOriginalPic;
1122     refListFull[currRefIdx]->bUsedAsRef            = m_hevcPicParams->bUsedAsRef;
1123     refListFull[currRefIdx]->resBitstreamBuffer = m_resBitstreamBuffer;
1124     refListFull[currRefIdx]->bFormatConversionDone = false;
1125 
1126     // P/B frames with empty ref lists are internally encoded as I frames,
1127     // while picture header packing remains the original value
1128     m_pictureCodingType = m_hevcPicParams->CodingType;
1129 
1130     bool emptyRefFrmList = true;
1131     for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
1132     {
1133         if (m_hevcPicParams->RefFrameList[i].PicFlags != PICTURE_INVALID)
1134         {
1135             emptyRefFrmList = false;
1136             break;
1137         }
1138     }
1139 
1140     if (emptyRefFrmList && m_pictureCodingType != I_TYPE)
1141     {
1142         // If there is no reference frame in the list, just mark the current picture as the I type
1143         m_pictureCodingType = I_TYPE;
1144     }
1145 
1146     for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
1147     {
1148         m_picIdx[i].bValid = false;
1149         if (m_hevcPicParams->RefFrameList[i].PicFlags != PICTURE_INVALID)
1150         {
1151             uint8_t index         = m_hevcPicParams->RefFrameList[i].FrameIdx;
1152             bool duplicatedIdx = false;
1153             for (auto ii = 0; ii < i; ii++)
1154             {
1155                 if (m_picIdx[ii].bValid && index == m_hevcPicParams->RefFrameList[ii].FrameIdx)
1156                 {
1157                     // We find the same FrameIdx in the ref_frame_list. Multiple reference frames are the same.
1158                     // In other words, RefFrameList[i] and RefFrameList[ii] have the same surface Id
1159                     duplicatedIdx = true;
1160                     break;
1161                 }
1162             }
1163 
1164             if (duplicatedIdx)
1165             {
1166                 continue;
1167             }
1168 
1169             // this reference frame in unique. Save it into the full reference list with 127 items
1170             refListFull[index]->RefPic.PicFlags =
1171                 CodecHal_CombinePictureFlags(refListFull[index]->RefPic, m_hevcPicParams->RefFrameList[i]);
1172             refListFull[index]->iFieldOrderCnt[0] = m_hevcPicParams->RefFramePOCList[i];
1173             refListFull[index]->iFieldOrderCnt[1] = m_hevcPicParams->RefFramePOCList[i];
1174             refListFull[index]->sRefBuffer        = m_hevcPicParams->bUseRawPicForRef ? refListFull[index]->sRefRawBuffer : refListFull[index]->sRefReconBuffer;
1175 
1176             m_picIdx[i].bValid   = true;
1177             m_picIdx[i].ucPicIdx = index;
1178         }
1179     }
1180 
1181     // Save the current RefList
1182     uint8_t ii = 0;
1183     for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
1184     {
1185         if (m_picIdx[i].bValid)
1186         {
1187             refListFull[currRefIdx]->RefList[ii] = m_hevcPicParams->RefFrameList[i];
1188             ii++;
1189         }
1190     }
1191     refListFull[currRefIdx]->ucNumRef = ii;
1192     m_currRefList = refListFull[currRefIdx];
1193 
1194     CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)m_encodeParams.pFeiPicParams;
1195     if ((m_codecFunction == CODECHAL_FUNCTION_ENC_PAK) ||
1196        ((m_codecFunction == CODECHAL_FUNCTION_FEI_ENC_PAK) && (feiPicParams->bCTBCmdCuRecordEnable == false)) ||
1197         (m_codecFunction == CODECHAL_FUNCTION_ENC_VDENC_PAK))
1198     {
1199         m_currMinus2MbCodeIndex = m_lastMbCodeIndex;
1200         m_lastMbCodeIndex       = m_currMbCodeIdx;
1201         // the actual MbCode/MvData surface to be allocated later
1202         m_trackedBuf->SetAllocationFlag(true);
1203     }
1204     else if (m_codecFunction == CODECHAL_FUNCTION_ENC)
1205     {
1206         CODECHAL_ENCODE_CHK_NULL_RETURN(m_encodeParams.presMbCodeSurface);
1207         m_resMbCodeSurface = *m_encodeParams.presMbCodeSurface;
1208     }
1209     else if(((m_codecFunction == CODECHAL_FUNCTION_FEI_ENC_PAK) && feiPicParams->bCTBCmdCuRecordEnable) ||
1210              (m_codecFunction == CODECHAL_FUNCTION_FEI_ENC) ||
1211              (m_codecFunction == CODECHAL_FUNCTION_FEI_PAK))
1212     {
1213         if(Mos_ResourceIsNull(&feiPicParams->resCURecord) || Mos_ResourceIsNull(&feiPicParams->resCTBCmd))
1214         {
1215             return MOS_STATUS_INVALID_PARAMETER;
1216         }
1217     }
1218 
1219     refListFull[currRefIdx]->iFieldOrderCnt[0] = m_hevcPicParams->CurrPicOrderCnt;
1220     refListFull[currRefIdx]->iFieldOrderCnt[1] = m_hevcPicParams->CurrPicOrderCnt;
1221 
1222     m_hmeEnabled    = m_hmeSupported && m_pictureCodingType != I_TYPE;
1223     m_b16XMeEnabled = m_16xMeSupported && m_pictureCodingType != I_TYPE;
1224     m_b32XMeEnabled = m_32xMeSupported && m_pictureCodingType != I_TYPE;
1225 
1226     CODECHAL_ENCODE_CHK_STATUS_RETURN(CalcLCUMaxCodingSize());
1227 
1228     // Screen content flag will come in with PPS on Linux/Android, but in SPS on other platforms,
1229     // we will use screen content flag in PPS for kernel programming, and update
1230     // the PPS screen content flag based on the SPS screen content flag if enabled.
1231     m_hevcPicParams->bScreenContent |= m_hevcSeqParams->bScreenContent;
1232 
1233     return eStatus;
1234 }
1235 
CalcLCUMaxCodingSize()1236 MOS_STATUS CodechalEncodeHevcBase::CalcLCUMaxCodingSize()
1237 {
1238     CODECHAL_ENCODE_FUNCTION_ENTER;
1239 
1240     uint16_t log2_max_coding_block_size = m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3;
1241     uint32_t rawCTUBits = (1 << (2 * log2_max_coding_block_size));
1242 
1243     switch (m_hevcSeqParams->chroma_format_idc)
1244     {
1245         // 420
1246     case 1:
1247         rawCTUBits = rawCTUBits * 3 / 2;
1248         break;
1249         // 422
1250     case 2:
1251         rawCTUBits = rawCTUBits * 2;
1252         break;
1253         // 444
1254     case 3:
1255         rawCTUBits = rawCTUBits * 3;
1256         break;
1257     default:
1258         break;
1259     };
1260 
1261     rawCTUBits = rawCTUBits * (m_hevcSeqParams->bit_depth_luma_minus8 + 8);
1262     rawCTUBits = (5 * rawCTUBits / 3);
1263 
1264     if (m_hevcPicParams->LcuMaxBitsizeAllowed == 0 || m_hevcPicParams->LcuMaxBitsizeAllowed > rawCTUBits)
1265     {
1266         m_hevcPicParams->LcuMaxBitsizeAllowed = rawCTUBits;
1267     }
1268 
1269     return MOS_STATUS_SUCCESS;
1270 }
1271 
SetSliceStructs()1272 MOS_STATUS CodechalEncodeHevcBase::SetSliceStructs()
1273 {
1274     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1275 
1276     CODECHAL_ENCODE_FUNCTION_ENTER;
1277 
1278     if (m_numSlices > m_maxNumSlicesSupported)
1279     {
1280         CODECHAL_ENCODE_ASSERTMESSAGE("Number of slice exceeds limit!");
1281         return MOS_STATUS_INVALID_PARAMETER;
1282     }
1283 
1284     // first slice must come with slice_segment_address = 0
1285     if (m_hevcSliceParams->slice_segment_address != 0)
1286     {
1287         CODECHAL_ENCODE_ASSERTMESSAGE("First slice segment_address != 0!");
1288         return MOS_STATUS_INVALID_PARAMETER;
1289     }
1290 
1291     m_refList[m_currReconstructedPic.FrameIdx]->ucQPValue[0] = m_hevcPicParams->QpY + m_hevcSliceParams->slice_qp_delta;
1292 
1293     m_lowDelay               = true;
1294     m_sameRefList            = true;
1295     m_arbitraryNumMbsInSlice = false;
1296 
1297     uint32_t lcuInRow  = MOS_ALIGN_CEIL(m_frameWidth, (1 << (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3))) >> (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3);
1298     auto     slcParams = m_hevcSliceParams;
1299     for (uint32_t startLCU = 0, slcCount = 0; slcCount < m_numSlices; slcCount++, slcParams++)
1300     {
1301         CODECHAL_ENCODE_CHK_STATUS_RETURN(ValidateRefFrameData(slcParams));
1302 
1303         if ((m_hevcPicParams->QpY + slcParams->slice_qp_delta) > CODECHAL_ENCODE_HEVC_MAX_SLICE_QP)
1304         {
1305             eStatus = MOS_STATUS_INVALID_PARAMETER;
1306             return eStatus;
1307         }
1308 
1309         CODECHAL_ENCODE_CHK_STATUS_RETURN(ValidateLowDelayBFrame(slcParams));
1310 
1311         CODECHAL_ENCODE_CHK_STATUS_RETURN(ValidateSameRefInL0L1(slcParams));
1312 
1313         if (m_arbitraryNumMbsInSlice == false && (slcParams->NumLCUsInSlice % lcuInRow))
1314         {
1315             // Slice number must be multiple of LCU rows
1316             m_arbitraryNumMbsInSlice = true;
1317         }
1318 
1319         if (!m_hevcPicParams->tiles_enabled_flag)
1320         {
1321             CODECHAL_ENCODE_ASSERT(slcParams->slice_segment_address == startLCU);
1322             startLCU += slcParams->NumLCUsInSlice;
1323         }
1324     }
1325 
1326     if (m_lowDelay && !m_sameRefList)
1327     {
1328         CODECHAL_ENCODE_NORMALMESSAGE("Attention: LDB frame but with different L0/L1 list !");
1329     }
1330 
1331     if (m_hevcSeqParams->RateControlMethod == RATECONTROL_VCM && m_pictureCodingType == B_TYPE && !m_lowDelay)
1332     {
1333         CODECHAL_ENCODE_ASSERTMESSAGE("VCM BRC mode does not support regular B-frames\n");
1334         return MOS_STATUS_INVALID_PARAMETER;
1335     }
1336 
1337     CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySliceSAOState());
1338 
1339 #if (_DEBUG || _RELEASE_INTERNAL)
1340     if (!m_vdencEnabled)
1341     {
1342         m_forceSinglePakPass = false;
1343         MOS_USER_FEATURE_VALUE_DATA userFeatureData;
1344         MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
1345         //read user feature key for pak pass number forcing.
1346         MOS_UserFeature_ReadValue_ID(
1347             nullptr,
1348             __MEDIA_USER_FEATURE_VALUE_FORCE_PAK_PASS_NUM_ID,
1349             &userFeatureData,
1350             m_osInterface->pOsContext);
1351         if (userFeatureData.u32Data > 0 && userFeatureData.u32Data <= m_numPasses)
1352         {
1353             m_numPasses = (uint8_t)userFeatureData.u32Data - 1;
1354             if (m_numPasses == 0)
1355             {
1356                 m_forceSinglePakPass = true;
1357                 CODECHAL_ENCODE_VERBOSEMESSAGE("Force to single PAK pass\n");
1358             }
1359         }
1360     }
1361 #endif
1362     return eStatus;
1363 }
1364 
ValidateSameRefInL0L1(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)1365 MOS_STATUS CodechalEncodeHevcBase::ValidateSameRefInL0L1(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)
1366 {
1367     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1368 
1369     CODECHAL_ENCODE_FUNCTION_ENTER;
1370 
1371     CODECHAL_ENCODE_CHK_NULL_RETURN(slcParams);
1372 
1373     if (m_sameRefList &&
1374         slcParams->num_ref_idx_l0_active_minus1 >= slcParams->num_ref_idx_l1_active_minus1)
1375     {
1376         for (int refIdx = 0; refIdx < slcParams->num_ref_idx_l1_active_minus1 + 1; refIdx++)
1377         {
1378             CODEC_PICTURE refPicL0 = slcParams->RefPicList[0][refIdx];
1379             CODEC_PICTURE refPicL1 = slcParams->RefPicList[1][refIdx];
1380 
1381             if (!CodecHal_PictureIsInvalid(refPicL0) && !CodecHal_PictureIsInvalid(refPicL1) && refPicL0.FrameIdx != refPicL1.FrameIdx)
1382             {
1383                 m_sameRefList = false;
1384                 break;
1385             }
1386         }
1387     }
1388 
1389     return eStatus;
1390 }
1391 
ValidateLowDelayBFrame(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)1392 MOS_STATUS CodechalEncodeHevcBase::ValidateLowDelayBFrame(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)
1393 {
1394     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1395 
1396     CODECHAL_ENCODE_FUNCTION_ENTER;
1397 
1398     CODECHAL_ENCODE_CHK_NULL_RETURN(slcParams);
1399 
1400     // Examine if now it is in the low delay mode
1401     if (slcParams->slice_type == CODECHAL_ENCODE_HEVC_B_SLICE && m_lowDelay)
1402     {
1403         // forward
1404         for (int refIdx = 0; (refIdx < slcParams->num_ref_idx_l0_active_minus1 + 1) && m_lowDelay; refIdx++)
1405         {
1406             if (refIdx >= CODEC_MAX_NUM_REF_FRAME_HEVC)
1407             {
1408                 break;
1409             }
1410 
1411             CODEC_PICTURE  refPic = slcParams->RefPicList[0][refIdx];
1412             if (!CodecHal_PictureIsInvalid(refPic) && m_hevcPicParams->RefFramePOCList[refPic.FrameIdx] > m_hevcPicParams->CurrPicOrderCnt)
1413             {
1414                 m_lowDelay = false;
1415             }
1416         }
1417 
1418         // backward
1419         for (int refIdx = 0; (refIdx < slcParams->num_ref_idx_l1_active_minus1 + 1) && m_lowDelay; refIdx++)
1420         {
1421             if (refIdx >= CODEC_MAX_NUM_REF_FRAME_HEVC)
1422             {
1423                 break;
1424             }
1425 
1426             CODEC_PICTURE refPic = slcParams->RefPicList[1][refIdx];
1427             if (!CodecHal_PictureIsInvalid(refPic) && m_hevcPicParams->RefFramePOCList[refPic.FrameIdx] > m_hevcPicParams->CurrPicOrderCnt)
1428             {
1429                 m_lowDelay = false;
1430             }
1431         }
1432     }
1433 
1434     return eStatus;
1435 }
1436 
VerifySliceSAOState()1437 MOS_STATUS CodechalEncodeHevcBase::VerifySliceSAOState()
1438 {
1439     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1440 
1441     CODECHAL_ENCODE_FUNCTION_ENTER;
1442 
1443     if (m_hevcSeqParams->SAO_enabled_flag)
1444     {
1445         auto     slcParams       = m_hevcSliceParams;
1446         uint32_t slcSaoLumaCount = 0, slcSaoChromaCount = 0;
1447 
1448         for (uint32_t slcCount = 0; slcCount < m_numSlices; slcCount++, slcParams++)
1449         {
1450             slcSaoLumaCount += slcParams->slice_sao_luma_flag;
1451             slcSaoChromaCount += slcParams->slice_sao_chroma_flag;
1452         }
1453 
1454         // For HCP_SLICE_STATE command, slices must have the same SAO setting within a picture for encoder.
1455         if (((slcSaoLumaCount > 0) && (slcSaoLumaCount != m_numSlices)) ||
1456             ((slcSaoChromaCount > 0) && (slcSaoChromaCount != m_numSlices)))
1457         {
1458             m_hevcSeqParams->SAO_enabled_flag = false;
1459             CODECHAL_ENCODE_ASSERTMESSAGE("Invalid SAO parameters in slice. All slices must have the same SAO setting within a picture.");
1460         }
1461     }
1462 
1463     m_uc2NdSaoPass = 0;  // Assume there is no 2nd SAO pass
1464 
1465     if (m_hevcSeqParams->SAO_enabled_flag && m_b2NdSaoPassNeeded)
1466     {
1467         m_numPasses = m_numPasses + 1; // one more pass for the 2nd SAO, i.e., BRC0, BRC1, ..., BRCn, and SAOn+1
1468         m_uc2NdSaoPass = m_numPasses;
1469     }
1470 
1471     return eStatus;
1472 }
1473 
UpdateYUY2SurfaceInfo(PMOS_SURFACE surface,bool is10Bit)1474 MOS_STATUS CodechalEncodeHevcBase::UpdateYUY2SurfaceInfo(
1475     PMOS_SURFACE        surface,
1476     bool                is10Bit)
1477 {
1478     CODECHAL_ENCODE_FUNCTION_ENTER;
1479 
1480     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1481 
1482     CODECHAL_ENCODE_CHK_NULL_RETURN(surface);
1483 
1484     if (Format_YUY2V == surface->Format ||
1485         Format_Y216V == surface->Format)
1486     {
1487         // surface has been updated
1488         return eStatus;
1489     }
1490 
1491     surface->Format = is10Bit ? Format_Y216V : Format_YUY2V;
1492     surface->dwWidth = m_oriFrameWidth;
1493     surface->dwHeight = m_oriFrameHeight;
1494 
1495     surface->YPlaneOffset.iXOffset = 0;
1496     surface->YPlaneOffset.iYOffset = 0;
1497 
1498     surface->UPlaneOffset.iSurfaceOffset = surface->YPlaneOffset.iSurfaceOffset + surface->dwHeight * surface->dwPitch;
1499     surface->UPlaneOffset.iXOffset = 0;
1500     surface->UPlaneOffset.iYOffset = surface->dwHeight;
1501 
1502     surface->VPlaneOffset.iSurfaceOffset = surface->UPlaneOffset.iSurfaceOffset;
1503     surface->VPlaneOffset.iXOffset = 0;
1504     surface->VPlaneOffset.iYOffset = surface->dwHeight;
1505 
1506     return eStatus;
1507 }
1508 
CreateFlatScalingList()1509 void CodechalEncodeHevcBase::CreateFlatScalingList()
1510 {
1511     CODECHAL_ENCODE_FUNCTION_ENTER;
1512 
1513     for (auto i = 0; i < 6; i++)
1514     {
1515         memset(&(m_hevcIqMatrixParams->ucScalingLists0[i][0]),
1516             0x10,
1517             sizeof(m_hevcIqMatrixParams->ucScalingLists0[i]));
1518 
1519         memset(&(m_hevcIqMatrixParams->ucScalingLists1[i][0]),
1520             0x10,
1521             sizeof(m_hevcIqMatrixParams->ucScalingLists1[i]));
1522 
1523         memset(&(m_hevcIqMatrixParams->ucScalingLists2[i][0]),
1524             0x10,
1525             sizeof(m_hevcIqMatrixParams->ucScalingLists2[i]));
1526     }
1527 
1528     memset(&(m_hevcIqMatrixParams->ucScalingLists3[0][0]),
1529         0x10,
1530         sizeof(m_hevcIqMatrixParams->ucScalingLists3[0]));
1531 
1532     memset(&(m_hevcIqMatrixParams->ucScalingLists3[1][0]),
1533         0x10,
1534         sizeof(m_hevcIqMatrixParams->ucScalingLists3[1]));
1535 
1536     memset(&(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID2[0]),
1537         0x10,
1538         sizeof(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID2));
1539 
1540     memset(&(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID3[0]),
1541         0x10,
1542         sizeof(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID3));
1543 }
1544 
CreateDefaultScalingList()1545 void CodechalEncodeHevcBase::CreateDefaultScalingList()
1546 {
1547     CODECHAL_ENCODE_FUNCTION_ENTER;
1548 
1549     const uint8_t flatScalingList4x4[16] =
1550     {
1551         16,16,16,16,
1552         16,16,16,16,
1553         16,16,16,16,
1554         16,16,16,16
1555     };
1556 
1557     const uint8_t defaultScalingList8x8[2][64] =
1558     {
1559         {
1560             16,16,16,16,17,18,21,24,
1561             16,16,16,16,17,19,22,25,
1562             16,16,17,18,20,22,25,29,
1563             16,16,18,21,24,27,31,36,
1564             17,17,20,24,30,35,41,47,
1565             18,19,22,27,35,44,54,65,
1566             21,22,25,31,41,54,70,88,
1567             24,25,29,36,47,65,88,115
1568         },
1569         {
1570             16,16,16,16,17,18,20,24,
1571             16,16,16,17,18,20,24,25,
1572             16,16,17,18,20,24,25,28,
1573             16,17,18,20,24,25,28,33,
1574             17,18,20,24,25,28,33,41,
1575             18,20,24,25,28,33,41,54,
1576             20,24,25,28,33,41,54,71,
1577             24,25,28,33,41,54,71,91
1578         }
1579     };
1580 
1581     for (auto i = 0; i < 6; i++)
1582     {
1583         memcpy(&(m_hevcIqMatrixParams->ucScalingLists0[i][0]),
1584             flatScalingList4x4,
1585             sizeof(m_hevcIqMatrixParams->ucScalingLists0[i]));
1586     }
1587 
1588     for (auto i = 0; i < 3; i++)
1589     {
1590         memcpy(&(m_hevcIqMatrixParams->ucScalingLists1[i][0]),
1591             defaultScalingList8x8[0],
1592             sizeof(m_hevcIqMatrixParams->ucScalingLists1[i]));
1593 
1594         memcpy(&(m_hevcIqMatrixParams->ucScalingLists1[3 + i][0]),
1595             defaultScalingList8x8[1],
1596             sizeof(m_hevcIqMatrixParams->ucScalingLists1[3 + i]));
1597 
1598         memcpy(&(m_hevcIqMatrixParams->ucScalingLists2[i][0]),
1599             defaultScalingList8x8[0],
1600             sizeof(m_hevcIqMatrixParams->ucScalingLists2[i]));
1601 
1602         memcpy(&(m_hevcIqMatrixParams->ucScalingLists2[3 + i][0]),
1603             defaultScalingList8x8[1],
1604             sizeof(m_hevcIqMatrixParams->ucScalingLists2[3 + i]));
1605     }
1606 
1607     memcpy(&(m_hevcIqMatrixParams->ucScalingLists3[0][0]),
1608         defaultScalingList8x8[0],
1609         sizeof(m_hevcIqMatrixParams->ucScalingLists3[0]));
1610 
1611     memcpy(&(m_hevcIqMatrixParams->ucScalingLists3[1][0]),
1612         defaultScalingList8x8[1],
1613         sizeof(m_hevcIqMatrixParams->ucScalingLists3[1]));
1614 
1615     memset(&(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID2[0]),
1616         0x10,
1617         sizeof(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID2));
1618 
1619     memset(&(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID3[0]),
1620         0x10,
1621         sizeof(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID3));
1622 }
1623 
VerifyCommandBufferSize()1624 MOS_STATUS CodechalEncodeHevcBase::VerifyCommandBufferSize()
1625 {
1626     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1627 
1628     CODECHAL_ENCODE_FUNCTION_ENTER;
1629 
1630     // resize CommandBuffer Size for every BRC pass
1631     if (!m_singleTaskPhaseSupported)
1632     {
1633         CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable());
1634     }
1635     return eStatus;
1636 }
1637 
GetCommandBuffer(PMOS_COMMAND_BUFFER cmdBuffer)1638 MOS_STATUS CodechalEncodeHevcBase::GetCommandBuffer(PMOS_COMMAND_BUFFER cmdBuffer)
1639 {
1640     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1641 
1642     CODECHAL_ENCODE_FUNCTION_ENTER;
1643 
1644     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
1645 
1646     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, cmdBuffer, 0));
1647 
1648     return eStatus;
1649 
1650 }
1651 
ReturnCommandBuffer(PMOS_COMMAND_BUFFER cmdBuffer)1652 MOS_STATUS CodechalEncodeHevcBase::ReturnCommandBuffer(PMOS_COMMAND_BUFFER cmdBuffer)
1653 {
1654     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1655 
1656     CODECHAL_ENCODE_FUNCTION_ENTER;
1657 
1658     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
1659 
1660     m_osInterface->pfnReturnCommandBuffer(m_osInterface, cmdBuffer, 0);
1661     return eStatus;
1662 }
1663 
SubmitCommandBuffer(PMOS_COMMAND_BUFFER cmdBuffer,bool bNullRendering)1664 MOS_STATUS CodechalEncodeHevcBase::SubmitCommandBuffer(
1665     PMOS_COMMAND_BUFFER cmdBuffer,
1666     bool                bNullRendering)
1667 {
1668     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1669 
1670     CODECHAL_ENCODE_FUNCTION_ENTER;
1671 
1672     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
1673 
1674     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, cmdBuffer, bNullRendering));
1675     return eStatus;
1676 }
1677 
SendPrologWithFrameTracking(PMOS_COMMAND_BUFFER cmdBuffer,bool frameTrackingRequested,MHW_MI_MMIOREGISTERS * mmioRegister)1678 MOS_STATUS CodechalEncodeHevcBase::SendPrologWithFrameTracking(
1679     PMOS_COMMAND_BUFFER         cmdBuffer,
1680     bool                        frameTrackingRequested,
1681     MHW_MI_MMIOREGISTERS       *mmioRegister)
1682 {
1683     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1684 
1685     CODECHAL_ENCODE_FUNCTION_ENTER;
1686 
1687     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
1688 
1689     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::SendPrologWithFrameTracking(cmdBuffer, frameTrackingRequested, mmioRegister));
1690 
1691     return eStatus;
1692 }
1693 
GetMaxMBPS(uint32_t levelIdc,uint32_t * maxMBPS,uint64_t * maxBytePerPic)1694 MOS_STATUS CodechalEncodeHevcBase::GetMaxMBPS(uint32_t levelIdc, uint32_t* maxMBPS, uint64_t* maxBytePerPic)
1695 {
1696     CODECHAL_ENCODE_FUNCTION_ENTER;
1697 
1698     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1699 
1700     CODECHAL_ENCODE_CHK_NULL_RETURN(maxMBPS);
1701     CODECHAL_ENCODE_CHK_NULL_RETURN(maxBytePerPic);
1702 
1703     switch (levelIdc)
1704     {
1705     case 30:
1706         *maxMBPS = 552960;
1707         *maxBytePerPic = 36864; break;
1708     case 60:
1709         *maxMBPS = 3686400;
1710         *maxBytePerPic = 122880; break;
1711     case 63:
1712         *maxMBPS = 7372800;
1713         *maxBytePerPic = 245760; break;
1714     case 90:
1715         *maxMBPS = 16588800;
1716         *maxBytePerPic = 552760; break;
1717     case 93:
1718         *maxMBPS = 33177600;
1719         *maxBytePerPic = 983040; break;
1720     case 120:
1721         *maxMBPS = 66846720;
1722         *maxBytePerPic = 2228224; break;
1723     case 123:
1724         *maxMBPS = 133693440;
1725         *maxBytePerPic = 2228224; break;
1726     case 150:
1727         *maxMBPS = 267386880;
1728         *maxBytePerPic = 8912896; break;
1729     case 153:
1730         *maxMBPS = 534773760;
1731         *maxBytePerPic = 8912896; break;
1732     case 156:
1733         *maxMBPS = 1069547520;
1734         *maxBytePerPic = 8912896; break;
1735     case 180:
1736         *maxMBPS = 1069547520;
1737         *maxBytePerPic = 35651584; break;
1738     case 183:
1739         *maxMBPS = 2139095040;
1740         *maxBytePerPic = 35651584; break;
1741     case 186:
1742         *maxMBPS = 4278190080;
1743         *maxBytePerPic = 35651584; break;
1744     default:
1745         *maxMBPS = 16588800;
1746         *maxBytePerPic = 552760; // CModel defaults to level 3.0 value if not found,
1747                               // we can do the same, just output that the issue exists and continue
1748         CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported LevelIDC setting for HEVC");
1749         break;
1750     }
1751 
1752     return eStatus;
1753 }
1754 
GetProfileLevelMaxFrameSize()1755 uint32_t CodechalEncodeHevcBase::GetProfileLevelMaxFrameSize()
1756 {
1757     CODECHAL_ENCODE_FUNCTION_ENTER;
1758 
1759     uint8_t         minCR = 2;
1760     float_t         formatFactor = 1.5;
1761     float_t         fminCrScale = 1.0;
1762     uint32_t        maxMBPS;
1763     uint64_t        maxBytePerPic;
1764     int32_t         levelIdc = m_hevcSeqParams->Level * 3;
1765 
1766     if (levelIdc == 186 || levelIdc == 150)
1767     {
1768         minCR = 6;
1769     }
1770     else if (levelIdc >150)
1771     {
1772         minCR = 8;
1773     }
1774     else if (levelIdc >93)
1775     {
1776         minCR = 4;
1777     }
1778 
1779     if (m_hevcSeqParams->chroma_format_idc == 0)
1780     {
1781         if (m_hevcSeqParams->bit_depth_luma_minus8 == 0)
1782             formatFactor = 1.0;
1783         else if (m_hevcSeqParams->bit_depth_luma_minus8 == 8)
1784             formatFactor = 2.0;
1785     }
1786     else if (m_hevcSeqParams->chroma_format_idc == 1)
1787     {
1788         if (m_hevcSeqParams->bit_depth_luma_minus8 == 2)
1789         {
1790             formatFactor = 1.875;
1791         }
1792         else if (m_hevcSeqParams->bit_depth_luma_minus8 == 4)
1793         {
1794             formatFactor = 2.25;
1795         }
1796     }
1797     else if (m_hevcSeqParams->chroma_format_idc == 2)
1798     {
1799         fminCrScale = 0.5;
1800         if (m_hevcSeqParams->bit_depth_luma_minus8 == 2)
1801         {
1802             formatFactor = 2.5;
1803         }
1804         else if (m_hevcSeqParams->bit_depth_luma_minus8 == 4)
1805         {
1806             formatFactor = 3.0;
1807         }
1808     }
1809     else
1810     {
1811         fminCrScale = 0.5;
1812         formatFactor = 3.0;
1813 
1814         if (m_hevcSeqParams->bit_depth_luma_minus8 == 2)
1815         {
1816             formatFactor = 3.75;
1817         }
1818         else if (m_hevcSeqParams->bit_depth_luma_minus8 == 4)
1819         {
1820             formatFactor = 4.5;
1821         }
1822     }
1823 
1824     fminCrScale *= minCR;
1825     formatFactor /= fminCrScale;
1826     GetMaxMBPS(levelIdc, &maxMBPS, &maxBytePerPic);
1827     auto     maxBytePerPicNot0    = (uint64_t)((((float_t)maxMBPS * (float_t)m_hevcSeqParams->FrameRate.Denominator) / (float_t)m_hevcSeqParams->FrameRate.Numerator) * formatFactor);
1828     uint32_t profileLevelMaxFrame = 0;
1829 
1830     uint32_t userMaxFrameSize = m_hevcSeqParams->UserMaxIFrameSize;
1831     if ((m_hevcPicParams->CodingType != I_TYPE) && (m_hevcSeqParams->UserMaxPBFrameSize > 0))
1832     {
1833         userMaxFrameSize = m_hevcSeqParams->UserMaxPBFrameSize;
1834     }
1835 
1836     if (userMaxFrameSize != 0)
1837     {
1838         profileLevelMaxFrame = (uint32_t)MOS_MIN(userMaxFrameSize, maxBytePerPic);
1839         profileLevelMaxFrame = (uint32_t)MOS_MIN(maxBytePerPicNot0, profileLevelMaxFrame);
1840     }
1841     else {
1842         profileLevelMaxFrame = (uint32_t)MOS_MIN(maxBytePerPicNot0, maxBytePerPic);
1843     }
1844 
1845     profileLevelMaxFrame = (uint32_t)MOS_MIN((m_frameHeight * m_frameWidth), profileLevelMaxFrame);
1846 
1847     return profileLevelMaxFrame;
1848 }
1849 
CalcTransformSkipParameters(MHW_VDBOX_ENCODE_HEVC_TRANSFORM_SKIP_PARAMS & params)1850 void CodechalEncodeHevcBase::CalcTransformSkipParameters(
1851     MHW_VDBOX_ENCODE_HEVC_TRANSFORM_SKIP_PARAMS& params)
1852 {
1853     CODECHAL_ENCODE_FUNCTION_ENTER;
1854 
1855     if (!m_hevcPicParams->transform_skip_enabled_flag)
1856     {
1857         return;
1858     }
1859 
1860     params.Transformskip_enabled = true;
1861     int sliceQP = CalSliceQp();
1862 
1863     int qpIdx = 0;
1864     if (sliceQP <= 22)
1865     {
1866         qpIdx = 0;
1867     }
1868     else if (sliceQP <= 27)
1869     {
1870         qpIdx = 1;
1871     }
1872     else if (sliceQP <= 32)
1873     {
1874         qpIdx = 2;
1875     }
1876     else
1877     {
1878         qpIdx = 3;
1879     }
1880 
1881     params.Transformskip_lambda = TransformSkipLambdaTable[sliceQP];
1882 
1883     if (m_hevcPicParams->CodingType == I_TYPE)
1884     {
1885         params.Transformskip_Numzerocoeffs_Factor0 = TransformSkipCoeffsTable[qpIdx][0][0][0][0];
1886         params.Transformskip_Numzerocoeffs_Factor1 = TransformSkipCoeffsTable[qpIdx][0][0][1][0];
1887         params.Transformskip_Numnonzerocoeffs_Factor0 = TransformSkipCoeffsTable[qpIdx][0][0][0][1] + 32;
1888         params.Transformskip_Numnonzerocoeffs_Factor1 = TransformSkipCoeffsTable[qpIdx][0][0][1][1] + 32;
1889     }
1890     else
1891     {
1892         params.Transformskip_Numzerocoeffs_Factor0 = TransformSkipCoeffsTable[qpIdx][1][0][0][0];
1893         params.Transformskip_Numzerocoeffs_Factor1 = TransformSkipCoeffsTable[qpIdx][1][0][1][0];
1894         params.Transformskip_Numnonzerocoeffs_Factor0 = TransformSkipCoeffsTable[qpIdx][1][0][0][1] + 32;
1895         params.Transformskip_Numnonzerocoeffs_Factor1 = TransformSkipCoeffsTable[qpIdx][1][0][1][1] + 32;
1896     }
1897 }
1898 
SetSemaphoreMem(PMOS_RESOURCE semaphoreMem,PMOS_COMMAND_BUFFER cmdBuffer,uint32_t value)1899 MOS_STATUS CodechalEncodeHevcBase::SetSemaphoreMem(
1900     PMOS_RESOURCE semaphoreMem,
1901     PMOS_COMMAND_BUFFER cmdBuffer,
1902     uint32_t value)
1903 {
1904     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1905 
1906     CODECHAL_ENCODE_FUNCTION_ENTER;
1907 
1908     CODECHAL_ENCODE_CHK_NULL_RETURN(semaphoreMem);
1909     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
1910 
1911     MHW_MI_STORE_DATA_PARAMS storeDataParams;
1912     MOS_ZeroMemory(&storeDataParams, sizeof(storeDataParams));
1913     storeDataParams.pOsResource = semaphoreMem;
1914     storeDataParams.dwResourceOffset = 0;
1915     storeDataParams.dwValue = value;
1916 
1917     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(
1918         cmdBuffer,
1919         &storeDataParams));
1920 
1921     return eStatus;
1922 }
1923 
SendHWWaitCommand(PMOS_RESOURCE semaphoreMem,PMOS_COMMAND_BUFFER cmdBuffer,uint32_t semValue)1924 MOS_STATUS CodechalEncodeHevcBase::SendHWWaitCommand(
1925     PMOS_RESOURCE semaphoreMem,
1926     PMOS_COMMAND_BUFFER cmdBuffer,
1927     uint32_t semValue)
1928 {
1929     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1930 
1931     CODECHAL_ENCODE_FUNCTION_ENTER;
1932 
1933     CODECHAL_ENCODE_CHK_NULL_RETURN(semaphoreMem);
1934     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
1935 
1936     MHW_MI_SEMAPHORE_WAIT_PARAMS miSemaphoreWaitParams;
1937     MOS_ZeroMemory(&miSemaphoreWaitParams, sizeof(miSemaphoreWaitParams));
1938     miSemaphoreWaitParams.presSemaphoreMem = semaphoreMem;
1939     miSemaphoreWaitParams.bPollingWaitMode = true;
1940     miSemaphoreWaitParams.dwSemaphoreData = semValue;
1941     miSemaphoreWaitParams.CompareOperation = MHW_MI_SAD_EQUAL_SDD;
1942 
1943     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiSemaphoreWaitCmd(cmdBuffer, &miSemaphoreWaitParams));
1944 
1945     return eStatus;
1946 }
1947 
SendMIAtomicCmd(PMOS_RESOURCE semaMem,uint32_t immData,MHW_COMMON_MI_ATOMIC_OPCODE opCode,PMOS_COMMAND_BUFFER cmdBuffer)1948 MOS_STATUS CodechalEncodeHevcBase::SendMIAtomicCmd(
1949     PMOS_RESOURCE               semaMem,
1950     uint32_t                    immData,
1951     MHW_COMMON_MI_ATOMIC_OPCODE opCode,
1952     PMOS_COMMAND_BUFFER         cmdBuffer
1953     )
1954 {
1955     MHW_MI_ATOMIC_PARAMS       atomicParams;
1956     MOS_STATUS                 eStatus = MOS_STATUS_SUCCESS;
1957 
1958     CODECHAL_ENCODE_FUNCTION_ENTER;
1959 
1960     MOS_ZeroMemory((&atomicParams), sizeof(atomicParams));
1961     atomicParams.pOsResource = semaMem;
1962     atomicParams.dwDataSize = sizeof(uint32_t);
1963     atomicParams.Operation = opCode;
1964     atomicParams.bInlineData = true;
1965     atomicParams.dwOperand1Data[0] = immData;
1966     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiAtomicCmd(cmdBuffer, &atomicParams));
1967 
1968     return eStatus;
1969 }
1970 
WaitForVDBOX(PMOS_COMMAND_BUFFER cmdBuffer)1971 MOS_STATUS CodechalEncodeHevcBase::WaitForVDBOX(PMOS_COMMAND_BUFFER cmdBuffer)
1972 {
1973     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1974 
1975     CODECHAL_ENCODE_FUNCTION_ENTER;
1976 
1977     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
1978 
1979     if (!m_firstFrame &&
1980         !Mos_ResourceIsNull(&m_refSync[m_lastMbCodeIndex].resSemaphoreMem.sResource))
1981     {
1982         CODECHAL_ENCODE_CHK_STATUS_RETURN(
1983             SendHWWaitCommand(
1984                 &m_refSync[m_lastMbCodeIndex].resSemaphoreMem.sResource,
1985                 cmdBuffer,
1986                 1));
1987     }
1988 
1989     //keep these codes here, in case later we need support parallel frame PAK (need more than one set of internal buffers used by PAK HW).
1990 #if 0
1991     if (m_pictureCodingType == I_TYPE)
1992     {
1993         return eStatus;
1994     }
1995 
1996     bool refHasBeenWaited[CODEC_NUM_TRACKED_BUFFERS] = { false };
1997 
1998     // check all reference frames. If one of them has not be waited, then it needs to be wait and ensure it has been encoded completely.
1999     PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams = pHevcSliceParams;
2000     for (uint32_t s = 0; s < m_numSlices; s++, slcParams++)
2001     {
2002         for (auto ll = 0; ll < 2; ll++)
2003         {
2004             uint32_t numRef = (ll == 0) ? slcParams->num_ref_idx_l0_active_minus1 :
2005                 slcParams->num_ref_idx_l1_active_minus1;
2006 
2007             for (uint32_t i = 0; i <= numRef; i++)
2008             {
2009                 CODEC_PICTURE refPic = slcParams->RefPicList[ll][i];
2010                 if (!CodecHal_PictureIsInvalid(refPic) &&
2011                     !CodecHal_PictureIsInvalid(pHevcPicParams->RefFrameList[refPic.FrameIdx]))
2012                 {
2013                     uint32_t idx = pHevcPicParams->RefFrameList[refPic.FrameIdx].FrameIdx;
2014                     uint8_t ucMbCodeIdx = pRefList[idx]->ucMbCodeIdx;
2015 
2016                     if (ucMbCodeIdx >= CODEC_NUM_TRACKED_BUFFERS)
2017                     {
2018                         // MB code index is wrong
2019                         eStatus = MOS_STATUS_INVALID_PARAMETER;
2020                         return eStatus;
2021                     }
2022 
2023                     if (refHasBeenWaited[ucMbCodeIdx] || Mos_ResourceIsNull(&RefSync[ucMbCodeIdx].resSemaphoreMem.sResource))
2024                     {
2025                         continue;
2026                     }
2027 
2028                     // Use HW wait command
2029                     CODECHAL_ENCODE_CHK_STATUS_RETURN(
2030                         SendHWWaitCommand(
2031                             &RefSync[ucMbCodeIdx].resSemaphoreMem.sResource,
2032                             cmdBuffer, 1));
2033 
2034                     refHasBeenWaited[ucMbCodeIdx] = true;
2035                 }
2036             }
2037         }
2038     }
2039 #endif
2040     return eStatus;
2041 }
2042 
ReadBrcPakStatistics(PMOS_COMMAND_BUFFER cmdBuffer,EncodeReadBrcPakStatsParams * params)2043 MOS_STATUS CodechalEncodeHevcBase::ReadBrcPakStatistics(
2044     PMOS_COMMAND_BUFFER cmdBuffer,
2045     EncodeReadBrcPakStatsParams* params)
2046 {
2047     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2048 
2049     CODECHAL_ENCODE_FUNCTION_ENTER;
2050 
2051     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
2052     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
2053     CODECHAL_ENCODE_CHK_NULL_RETURN(params->presBrcPakStatisticBuffer);
2054     CODECHAL_ENCODE_CHK_NULL_RETURN(params->presStatusBuffer);
2055 
2056     if (m_vdboxIndex > m_mfxInterface->GetMaxVdboxIndex())                                                                         \
2057     {
2058         CODECHAL_ENCODE_ASSERTMESSAGE("ERROR - vdbox index exceed the maximum");
2059         eStatus = MOS_STATUS_INVALID_PARAMETER;
2060         return eStatus;
2061     }
2062 
2063     auto mmioRegisters = m_hcpInterface->GetMmioRegisters(m_vdboxIndex);
2064     CODECHAL_ENCODE_CHK_NULL_RETURN(mmioRegisters);
2065     MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
2066     MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
2067     miStoreRegMemParams.presStoreBuffer = params->presBrcPakStatisticBuffer;
2068     miStoreRegMemParams.dwOffset = CODECHAL_OFFSETOF(CODECHAL_ENCODE_HEVC_PAK_STATS_BUFFER, HCP_BITSTREAM_BYTECOUNT_FRAME);
2069     miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncBitstreamBytecountFrameRegOffset;
2070     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2071 
2072     MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
2073     miStoreRegMemParams.presStoreBuffer = params->presBrcPakStatisticBuffer;
2074     miStoreRegMemParams.dwOffset = CODECHAL_OFFSETOF(CODECHAL_ENCODE_HEVC_PAK_STATS_BUFFER, HCP_BITSTREAM_BYTECOUNT_FRAME_NOHEADER);
2075     miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncBitstreamBytecountFrameNoHeaderRegOffset;
2076     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2077 
2078     MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
2079     miStoreRegMemParams.presStoreBuffer = params->presBrcPakStatisticBuffer;
2080     miStoreRegMemParams.dwOffset = CODECHAL_OFFSETOF(CODECHAL_ENCODE_HEVC_PAK_STATS_BUFFER, HCP_IMAGE_STATUS_CONTROL);
2081     miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusCtrlRegOffset;
2082     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2083 
2084     MHW_MI_STORE_DATA_PARAMS storeDataParams;
2085     storeDataParams.pOsResource = params->presStatusBuffer;
2086     storeDataParams.dwResourceOffset = params->dwStatusBufNumPassesOffset;
2087     storeDataParams.dwValue = params->ucPass;
2088     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(cmdBuffer, &storeDataParams));
2089 
2090     return eStatus;
2091 }
2092 
ReadHcpStatus(PMOS_COMMAND_BUFFER cmdBuffer)2093 MOS_STATUS CodechalEncodeHevcBase::ReadHcpStatus(PMOS_COMMAND_BUFFER cmdBuffer)
2094 {
2095     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2096 
2097     CODECHAL_ENCODE_FUNCTION_ENTER;
2098 
2099     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
2100 
2101     EncodeStatusBuffer *encodeStatusBuf = &m_encodeStatusBuf;
2102 
2103     uint32_t baseOffset =
2104         (encodeStatusBuf->wCurrIndex * encodeStatusBuf->dwReportSize) +
2105         sizeof(uint32_t) * 2;  // pEncodeStatus is offset by 2 DWs in the resource
2106 
2107     MHW_MI_FLUSH_DW_PARAMS flushDwParams;
2108     MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
2109     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &flushDwParams));
2110 
2111     auto mmioRegisters = m_hcpInterface->GetMmioRegisters(m_vdboxIndex);
2112     CODECHAL_ENCODE_CHK_NULL_RETURN(mmioRegisters);
2113     MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
2114     MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
2115     miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
2116     miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwBSByteCountOffset;
2117     miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncBitstreamBytecountFrameRegOffset;
2118     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2119 
2120     MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
2121     miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
2122     miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwBSSEBitCountOffset;
2123     miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncBitstreamSeBitcountFrameRegOffset;
2124     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2125 
2126     MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
2127     miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
2128     miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwQpStatusCountOffset;
2129     miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncQpStatusCountRegOffset;
2130     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2131 
2132     return eStatus;
2133 }
2134 
ReadImageStatus(PMOS_COMMAND_BUFFER cmdBuffer)2135 MOS_STATUS CodechalEncodeHevcBase::ReadImageStatus(PMOS_COMMAND_BUFFER cmdBuffer)
2136 {
2137     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2138 
2139     CODECHAL_ENCODE_FUNCTION_ENTER;
2140 
2141     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
2142 
2143     EncodeStatusBuffer *encodeStatusBuf = &m_encodeStatusBuf;
2144 
2145     uint32_t baseOffset =
2146         (encodeStatusBuf->wCurrIndex * encodeStatusBuf->dwReportSize) +
2147         sizeof(uint32_t) * 2;  // pEncodeStatus is offset by 2 DWs in the resource
2148 
2149     auto mmioRegisters = m_hcpInterface->GetMmioRegisters(m_vdboxIndex);
2150     CODECHAL_ENCODE_CHK_NULL_RETURN(mmioRegisters);
2151     MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
2152     MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
2153     miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
2154     miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwImageStatusMaskOffset;
2155     miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusMaskRegOffset;
2156     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2157 
2158     MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
2159     miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
2160     miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwImageStatusCtrlOffset;
2161     miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusCtrlRegOffset;
2162     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
2163 
2164     MHW_MI_FLUSH_DW_PARAMS flushDwParams;
2165     MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
2166     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &flushDwParams));
2167 
2168     return eStatus;
2169 }
2170 
UserFeatureKeyReport()2171 MOS_STATUS CodechalEncodeHevcBase::UserFeatureKeyReport()
2172 {
2173     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2174     MediaUserSettingSharedPtr       userSettingPtr = nullptr;
2175 
2176     CODECHAL_ENCODE_FUNCTION_ENTER;
2177 
2178     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::UserFeatureKeyReport())
2179 
2180     CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_MODE_ID, m_codecFunction, m_osInterface->pOsContext);
2181     CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_ME_ENABLE_ID, m_hmeSupported, m_osInterface->pOsContext);
2182     CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_16xME_ENABLE_ID, m_16xMeSupported, m_osInterface->pOsContext);
2183     CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_32xME_ENABLE_ID, m_32xMeSupported, m_osInterface->pOsContext);
2184     CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_26Z_ENABLE_ID, (!m_enable26WalkingPattern), m_osInterface->pOsContext);
2185     CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_ENCODE_RATECONTROL_METHOD_ID, m_hevcSeqParams->RateControlMethod, m_osInterface->pOsContext);
2186 
2187 #if (_DEBUG || _RELEASE_INTERNAL)
2188     userSettingPtr = m_osInterface->pfnGetUserSettingInstance(m_osInterface);
2189     ReportUserSettingForDebug(
2190         userSettingPtr,
2191         __MEDIA_USER_FEATURE_VALUE_SIM_IN_USE,
2192         m_osInterface->bSimIsActive,
2193         MediaUserSetting::Group::Device);
2194     CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_RDOQ_ENABLE_ID, m_hevcRdoqEnabled, m_osInterface->pOsContext);
2195 #endif
2196 
2197     return eStatus;
2198 }
2199 
GetStatusReport(EncodeStatus * encodeStatus,EncodeStatusReport * encodeStatusReport)2200 MOS_STATUS CodechalEncodeHevcBase::GetStatusReport(
2201     EncodeStatus *encodeStatus,
2202     EncodeStatusReport *encodeStatusReport)
2203 {
2204     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2205 
2206     CODECHAL_ENCODE_FUNCTION_ENTER;
2207 
2208     CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatus);
2209     CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatusReport);
2210 
2211     // The last pass of BRC may have a zero value of hcpCumulativeFrameDeltaQp
2212     if (encodeStatus->ImageStatusCtrl.hcpTotalPass && encodeStatus->ImageStatusCtrl.hcpCumulativeFrameDeltaQp == 0)
2213     {
2214         encodeStatus->ImageStatusCtrl.hcpCumulativeFrameDeltaQp = encodeStatus->ImageStatusCtrlOfLastBRCPass.hcpCumulativeFrameDeltaQp;
2215     }
2216     encodeStatus->ImageStatusCtrlOfLastBRCPass.hcpCumulativeFrameDeltaQp = 0;
2217 
2218     encodeStatusReport->CodecStatus = CODECHAL_STATUS_SUCCESSFUL;
2219     encodeStatusReport->bitstreamSize = encodeStatus->dwMFCBitstreamByteCountPerFrame + encodeStatus->dwHeaderBytesInserted;
2220 
2221     encodeStatusReport->PanicMode = encodeStatus->ImageStatusCtrl.Panic;
2222     encodeStatusReport->AverageQp = 0;
2223     encodeStatusReport->QpY = 0;
2224     encodeStatusReport->SuggestedQpYDelta = encodeStatus->ImageStatusCtrl.hcpCumulativeFrameDeltaQp;
2225     encodeStatusReport->NumberPasses = (unsigned char)encodeStatus->ImageStatusCtrl.hcpTotalPass + 1; //initial pass is considered to be 0,hence +1 to report;
2226     CODECHAL_ENCODE_VERBOSEMESSAGE("Single Pipe Mode Exectued PAK Pass number: %d\n", encodeStatusReport->NumberPasses);
2227 
2228     if (m_frameWidth != 0 && m_frameHeight != 0)
2229     {
2230         uint32_t log2LcuSize = 2;
2231 
2232         //The CumulativeQp from the PAK has accumulation unit of LCU, so we align and divide height, width by LCU size
2233         if ((m_codecFunction == CODECHAL_FUNCTION_FEI_ENC_PAK) ||
2234             (m_codecFunction == (CODECHAL_FUNCTION_FEI_ENC | CODECHAL_FUNCTION_FEI_ENC_PAK)))
2235         {
2236             log2LcuSize = m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3;
2237         }
2238 
2239         // Based on HW team:
2240         // The CumulativeQp from the PAK accumulated at TU level and normalized to TU4x4
2241         // qp(for TU 8x8) = qp*4
2242         // qp(for TU 16x16) = qp *16
2243         // qp(for TU 32x32) = qp*64
2244         // all these qp are accumulated for entire frame.
2245         // the HW will ceil the CumulativeQp number to max (24 bit)
2246 
2247         encodeStatusReport->QpY = encodeStatusReport->AverageQp =
2248             (uint8_t)(((uint32_t)encodeStatus->QpStatusCount.hcpCumulativeQP)
2249                 / ((MOS_ALIGN_CEIL(m_frameWidth, (1 << log2LcuSize)) >> log2LcuSize) *
2250                 (MOS_ALIGN_CEIL(m_frameHeight, (1 << log2LcuSize)) >> log2LcuSize)));
2251     }
2252 
2253     if (!Mos_ResourceIsNull(&m_resFrameStatStreamOutBuffer))
2254     {
2255         CODECHAL_ENCODE_CHK_STATUS_RETURN(CalculatePSNR(encodeStatus, encodeStatusReport));
2256     }
2257     return eStatus;
2258 }
2259 
InitializePicture(const EncoderParams & params)2260 MOS_STATUS CodechalEncodeHevcBase::InitializePicture(const EncoderParams& params)
2261 {
2262     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2263 
2264     CODECHAL_ENCODE_FUNCTION_ENTER;
2265 
2266     m_hevcSeqParams      = (PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS)(params.pSeqParams);
2267     m_hevcPicParams      = (PCODEC_HEVC_ENCODE_PICTURE_PARAMS)(params.pPicParams);
2268     m_hevcSliceParams    = (PCODEC_HEVC_ENCODE_SLICE_PARAMS)params.pSliceParams;
2269     m_hevcFeiPicParams   = (CodecEncodeHevcFeiPicParams *)params.pFeiPicParams;
2270     m_hevcIqMatrixParams = (PCODECHAL_HEVC_IQ_MATRIX_PARAMS)params.pIQMatrixBuffer;
2271     m_nalUnitParams      = params.ppNALUnitParams;
2272 
2273     CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcSeqParams);
2274     CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcPicParams);
2275     CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcSliceParams);
2276     CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcIqMatrixParams);
2277     CODECHAL_ENCODE_CHK_NULL_RETURN(m_nalUnitParams);
2278 
2279     CODECHAL_ENCODE_CHK_STATUS_RETURN(PlatformCapabilityCheck());
2280 
2281     if (CodecHalIsFeiEncode(m_codecFunction))
2282     {
2283         CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcFeiPicParams);
2284         m_hevcSeqParams->TargetUsage = 0x04;
2285     }
2286 
2287     if (m_newSeq)
2288     {
2289         CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSequenceStructs());
2290 
2291         if (m_hevcSeqParams->log2_min_coding_block_size_minus3)
2292         {
2293             m_cscDsState->SetHcpReconAlignment(1 << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3));
2294         }
2295     }
2296 
2297     if (const_cast<EncoderParams *>(&params)->bAcceleratorHeaderPackingCaps)
2298     {
2299         HevcHeaderPacker Packer;
2300         Packer.SliceHeaderPacker(const_cast<EncoderParams *>(&params));
2301     }
2302 
2303     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetPictureStructs());
2304     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSliceStructs());
2305 
2306     // Scaling occurs when either HME or BRC is enabled
2307     m_scalingEnabled = m_hmeSupported || m_brcEnabled;
2308     m_useRawForRef   = m_hevcPicParams->bUseRawPicForRef;
2309 
2310     if (m_hevcPicParams->SkipFrameFlag == FRAME_SKIP_NORMAL)
2311     {
2312         m_skipFrameFlag  = m_hevcPicParams->SkipFrameFlag;
2313         m_numSkipFrames  = m_hevcPicParams->NumSkipFrames;
2314         m_sizeSkipFrames = m_hevcPicParams->SizeSkipFrames;
2315     }
2316 
2317     m_pictureStatesSize    = m_defaultPictureStatesSize;
2318     m_picturePatchListSize = m_defaultPicturePatchListSize;
2319 
2320     m_sliceStatesSize    = m_defaultSliceStatesSize;
2321     m_slicePatchListSize = m_defaultSlicePatchListSize;
2322 
2323     // Mb Qp data
2324     m_mbQpDataEnabled = params.bMbQpDataEnabled;
2325     if (m_mbQpDataEnabled)
2326     {
2327         m_mbQpDataSurface = *(params.psMbQpDataSurface);
2328     }
2329 
2330     CODECHAL_DEBUG_TOOL(
2331         m_debugInterface->m_currPic            = m_hevcPicParams->CurrOriginalPic;
2332         m_debugInterface->m_bufferDumpFrameNum = m_storeData;
2333         m_debugInterface->m_frameType          = m_pictureCodingType;
2334 
2335         if (m_newSeq) {
2336             CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpSeqParams(
2337                 m_hevcSeqParams));
2338         }
2339 
2340         CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpPicParams(
2341             m_hevcPicParams));
2342 
2343         if (CodecHalIsFeiEncode(m_codecFunction)) {
2344             CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpFeiPicParams(
2345                 m_hevcFeiPicParams));
2346         }
2347 
2348         for (uint32_t i = 0; i < m_numSlices; i++) {
2349             CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpSliceParams(
2350                 &m_hevcSliceParams[i],
2351                 m_hevcPicParams));
2352         })
2353 
2354     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetStatusReportParams(
2355         m_refList[m_currReconstructedPic.FrameIdx]));
2356 
2357     m_bitstreamUpperBound = m_encodeParams.dwBitstreamSize;
2358 
2359     return eStatus;
2360 }
2361 
SetHcpPipeModeSelectParams(MHW_VDBOX_PIPE_MODE_SELECT_PARAMS & pipeModeSelectParams)2362 void CodechalEncodeHevcBase::SetHcpPipeModeSelectParams(MHW_VDBOX_PIPE_MODE_SELECT_PARAMS& pipeModeSelectParams)
2363 {
2364     pipeModeSelectParams = {};
2365     pipeModeSelectParams.Mode = m_mode;
2366     pipeModeSelectParams.bStreamOutEnabled = m_vdencEnabled;
2367     pipeModeSelectParams.bVdencEnabled = m_vdencEnabled;
2368     pipeModeSelectParams.bRdoqEnable = m_hevcRdoqEnabled ? (m_pictureCodingType == I_TYPE ? m_hevcIFrameRdoqEnabled : 1) : 0;
2369     pipeModeSelectParams.bAdvancedRateControlEnable = m_vdencBrcEnabled;
2370 
2371     if (m_hevcSeqParams->SAO_enabled_flag)
2372     {
2373         // uses pipe mode select command to tell if this is the first or second pass of SAO
2374         pipeModeSelectParams.bSaoFirstPass = !IsLastPass();
2375 
2376         if (m_singleTaskPhaseSupportedInPak &&
2377             m_b2NdSaoPassNeeded &&
2378             m_brcEnabled)
2379         {
2380             if (GetCurrentPass() == m_uc2NdSaoPass - 1)  // the last BRC pass. This separates BRC passes and the 2nd pass SAO into different DMA buffer submissions
2381             {
2382                 m_lastTaskInPhase = true;
2383             }
2384             else if (GetCurrentPass() == m_uc2NdSaoPass)  // the 2nd SAO pass
2385             {
2386                 m_firstTaskInPhase = true;
2387                 m_lastTaskInPhase = true;
2388             }
2389         }
2390     }
2391 }
2392 
SetHcpSrcSurfaceParams(MHW_VDBOX_SURFACE_PARAMS & srcSurfaceParams)2393 void CodechalEncodeHevcBase::SetHcpSrcSurfaceParams(MHW_VDBOX_SURFACE_PARAMS& srcSurfaceParams)
2394 {
2395     MOS_ZeroMemory(&srcSurfaceParams, sizeof(srcSurfaceParams));
2396     srcSurfaceParams.Mode = m_mode;
2397     srcSurfaceParams.psSurface = m_rawSurfaceToPak;
2398     srcSurfaceParams.ucSurfaceStateId = CODECHAL_HCP_SRC_SURFACE_ID;
2399     srcSurfaceParams.ucBitDepthLumaMinus8   = m_hevcSeqParams->bit_depth_luma_minus8;
2400     srcSurfaceParams.ucBitDepthChromaMinus8 = m_hevcSeqParams->bit_depth_chroma_minus8;
2401     srcSurfaceParams.bDisplayFormatSwizzle  = m_hevcPicParams->bDisplayFormatSwizzle;
2402     srcSurfaceParams.ChromaType = m_outputChromaFormat;
2403     srcSurfaceParams.bSrc8Pak10Mode         = false; //No usage for 8->10 bit encode
2404     srcSurfaceParams.dwActualHeight = ((m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3));
2405 #ifdef _MMC_SUPPORTED
2406     m_mmcState->SetSurfaceState(&srcSurfaceParams);
2407 #endif
2408 }
2409 
SetHcpReconSurfaceParams(MHW_VDBOX_SURFACE_PARAMS & reconSurfaceParams)2410 void CodechalEncodeHevcBase::SetHcpReconSurfaceParams(MHW_VDBOX_SURFACE_PARAMS& reconSurfaceParams)
2411 {
2412     MOS_ZeroMemory(&reconSurfaceParams, sizeof(reconSurfaceParams));
2413     reconSurfaceParams.Mode = m_mode;
2414     reconSurfaceParams.psSurface = &m_reconSurface;
2415     reconSurfaceParams.ucSurfaceStateId = CODECHAL_HCP_DECODED_SURFACE_ID;
2416     reconSurfaceParams.ucBitDepthLumaMinus8   = m_hevcSeqParams->bit_depth_luma_minus8;
2417     reconSurfaceParams.ucBitDepthChromaMinus8 = m_hevcSeqParams->bit_depth_chroma_minus8;
2418     reconSurfaceParams.ChromaType = m_outputChromaFormat;
2419     reconSurfaceParams.dwActualHeight         = ((m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3));
2420     reconSurfaceParams.dwReconSurfHeight = m_rawSurfaceToPak->dwHeight;
2421 #ifdef _MMC_SUPPORTED
2422     m_mmcState->SetSurfaceState(&reconSurfaceParams);
2423 #endif
2424 }
2425 
SetHcpRefSurfaceParams(MHW_VDBOX_SURFACE_PARAMS & refSurfaceParams)2426 void CodechalEncodeHevcBase::SetHcpRefSurfaceParams(MHW_VDBOX_SURFACE_PARAMS &refSurfaceParams)
2427 {
2428     MOS_ZeroMemory(&refSurfaceParams, sizeof(refSurfaceParams));
2429     refSurfaceParams.Mode                     = m_mode;
2430     refSurfaceParams.psSurface                = &m_reconSurface;
2431     refSurfaceParams.ucSurfaceStateId         = CODECHAL_HCP_REF_SURFACE_ID;
2432     refSurfaceParams.ucBitDepthLumaMinus8     = m_hevcSeqParams->bit_depth_luma_minus8;
2433     refSurfaceParams.ucBitDepthChromaMinus8   = m_hevcSeqParams->bit_depth_chroma_minus8;
2434     refSurfaceParams.ChromaType               = m_outputChromaFormat;
2435     refSurfaceParams.dwActualHeight           = ((m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3));
2436     refSurfaceParams.dwReconSurfHeight        = m_rawSurfaceToPak->dwHeight;
2437 #ifdef _MMC_SUPPORTED
2438     m_mmcState->SetSurfaceState(&refSurfaceParams);
2439 #endif
2440 }
2441 
SetHcpPipeBufAddrParams(MHW_VDBOX_PIPE_BUF_ADDR_PARAMS & pipeBufAddrParams)2442 void CodechalEncodeHevcBase::SetHcpPipeBufAddrParams(MHW_VDBOX_PIPE_BUF_ADDR_PARAMS& pipeBufAddrParams)
2443 {
2444     CODECHAL_ENCODE_FUNCTION_ENTER;
2445 
2446     pipeBufAddrParams = {};
2447     pipeBufAddrParams.Mode = m_mode;
2448     pipeBufAddrParams.psPreDeblockSurface = &m_reconSurface;
2449     pipeBufAddrParams.psPostDeblockSurface = &m_reconSurface;
2450     pipeBufAddrParams.psRawSurface = m_rawSurfaceToPak;
2451     pipeBufAddrParams.presStreamOutBuffer = m_vdencEnabled ? &m_resStreamOutBuffer[0] : nullptr;
2452     pipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer    = &m_resDeblockingFilterRowStoreScratchBuffer;
2453     pipeBufAddrParams.presDeblockingFilterTileRowStoreScratchBuffer   = &m_resDeblockingFilterTileRowStoreScratchBuffer;
2454     pipeBufAddrParams.presDeblockingFilterColumnRowStoreScratchBuffer = &m_resDeblockingFilterColumnRowStoreScratchBuffer;
2455 
2456     pipeBufAddrParams.presMetadataLineBuffer        = &m_resMetadataLineBuffer;
2457     pipeBufAddrParams.presMetadataTileLineBuffer    = &m_resMetadataTileLineBuffer;
2458     pipeBufAddrParams.presMetadataTileColumnBuffer  = &m_resMetadataTileColumnBuffer;
2459     pipeBufAddrParams.presSaoLineBuffer             = &m_resSaoLineBuffer;
2460     pipeBufAddrParams.presSaoTileLineBuffer         = &m_resSaoTileLineBuffer;
2461     pipeBufAddrParams.presSaoTileColumnBuffer       = &m_resSaoTileColumnBuffer;
2462     pipeBufAddrParams.presCurMvTempBuffer = m_trackedBuf->GetMvTemporalBuffer(CODEC_CURR_TRACKED_BUFFER);
2463     pipeBufAddrParams.presLcuBaseAddressBuffer      = &m_resLcuBaseAddressBuffer;
2464     pipeBufAddrParams.dwLcuStreamOutOffset = 0;
2465     pipeBufAddrParams.presLcuILDBStreamOutBuffer    = &m_resLcuIldbStreamOutBuffer;
2466     pipeBufAddrParams.presSaoStreamOutBuffer        = &m_resSaoStreamOutBuffer;
2467     pipeBufAddrParams.presFrameStatStreamOutBuffer  = &m_resFrameStatStreamOutBuffer;
2468     pipeBufAddrParams.dwFrameStatStreamOutOffset =  0;
2469     pipeBufAddrParams.presSseSrcPixelRowStoreBuffer = &m_resSseSrcPixelRowStoreBuffer;
2470     pipeBufAddrParams.presPakCuLevelStreamoutBuffer =
2471         Mos_ResourceIsNull(&m_resPakcuLevelStreamoutData.sResource) ? nullptr : &m_resPakcuLevelStreamoutData.sResource;
2472     pipeBufAddrParams.bRawIs10Bit = m_is10BitHevc;
2473 
2474     //add for B frame support
2475     if (m_pictureCodingType != I_TYPE)
2476     {
2477         for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
2478         {
2479             if (!m_picIdx[i].bValid || !m_currUsedRefPic[i])
2480             {
2481                 continue;
2482             }
2483 
2484             uint8_t idx = m_picIdx[i].ucPicIdx;
2485             CodecHalGetResourceInfo(m_osInterface, &(m_refList[idx]->sRefReconBuffer));
2486 
2487             uint8_t frameStoreId                           = (uint8_t)m_refIdxMapping[i];
2488             pipeBufAddrParams.presReferences[frameStoreId] = &(m_refList[idx]->sRefReconBuffer.OsResource);
2489 
2490             uint8_t refMbCodeIdx = m_refList[idx]->ucScalingIdx;
2491             pipeBufAddrParams.presColMvTempBuffer[frameStoreId] = m_trackedBuf->GetMvTemporalBuffer(refMbCodeIdx);
2492         }
2493     }
2494 }
2495 
SetHcpIndObjBaseAddrParams(MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS & indObjBaseAddrParams)2496 void CodechalEncodeHevcBase::SetHcpIndObjBaseAddrParams(MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS& indObjBaseAddrParams)
2497 {
2498     MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams));
2499     indObjBaseAddrParams.Mode = CODECHAL_ENCODE_MODE_HEVC;
2500     indObjBaseAddrParams.presMvObjectBuffer = &m_resMbCodeSurface;
2501     indObjBaseAddrParams.dwMvObjectOffset = m_mvOffset;
2502     indObjBaseAddrParams.dwMvObjectSize = m_mbCodeSize - m_mvOffset;
2503     indObjBaseAddrParams.presPakBaseObjectBuffer = &m_resBitstreamBuffer;
2504     indObjBaseAddrParams.dwPakBaseObjectSize =m_bitstreamUpperBound;
2505     indObjBaseAddrParams.presPakTileSizeStasBuffer =  nullptr;
2506     indObjBaseAddrParams.dwPakTileSizeStasBufferSize = 0;
2507     indObjBaseAddrParams.dwPakTileSizeRecordOffset = 0;
2508 }
2509 
SetHcpQmStateParams(MHW_VDBOX_QM_PARAMS & fqmParams,MHW_VDBOX_QM_PARAMS & qmParams)2510 void CodechalEncodeHevcBase::SetHcpQmStateParams(MHW_VDBOX_QM_PARAMS& fqmParams, MHW_VDBOX_QM_PARAMS& qmParams)
2511 {
2512     MOS_ZeroMemory(&fqmParams, sizeof(fqmParams));
2513     fqmParams.Standard = CODECHAL_HEVC;
2514     fqmParams.pHevcIqMatrix = (PMHW_VDBOX_HEVC_QM_PARAMS)m_hevcIqMatrixParams;
2515 
2516     MOS_ZeroMemory(&qmParams, sizeof(qmParams));
2517     qmParams.Standard = CODECHAL_HEVC;
2518     qmParams.pHevcIqMatrix = (PMHW_VDBOX_HEVC_QM_PARAMS)m_hevcIqMatrixParams;
2519 }
2520 
SetHcpPicStateParams(MHW_VDBOX_HEVC_PIC_STATE & picStateParams)2521 void CodechalEncodeHevcBase::SetHcpPicStateParams(MHW_VDBOX_HEVC_PIC_STATE& picStateParams)
2522 {
2523     CODECHAL_ENCODE_FUNCTION_ENTER;
2524 
2525     picStateParams = {};
2526     picStateParams.pHevcEncSeqParams     = m_hevcSeqParams;
2527     picStateParams.pHevcEncPicParams     = m_hevcPicParams;
2528     picStateParams.bSAOEnable            = m_hevcSeqParams->SAO_enabled_flag ? (m_hevcSliceParams->slice_sao_luma_flag || m_hevcSliceParams->slice_sao_chroma_flag) : 0;
2529     picStateParams.bUseVDEnc = m_vdencEnabled;
2530     picStateParams.bNotFirstPass = m_vdencEnabled && !IsFirstPass() ;
2531     picStateParams.bHevcRdoqEnabled = m_hevcRdoqEnabled ? (m_pictureCodingType == I_TYPE ? m_hevcIFrameRdoqEnabled : 1) : 0;
2532     picStateParams.bRDOQIntraTUDisable   = m_hevcRdoqEnabled && (1 != m_hevcSeqParams->TargetUsage);
2533     picStateParams.wRDOQIntraTUThreshold = (uint16_t)m_rdoqIntraTuThreshold;
2534     picStateParams.bTransformSkipEnable  = m_hevcPicParams->transform_skip_enabled_flag;
2535 
2536 #if (_DEBUG || _RELEASE_INTERNAL)
2537     if (m_rdoqIntraTuOverride)
2538     {
2539         int32_t RDOQIntraTUThreshold = 0;
2540 
2541         if (m_rdoqIntraTuThresholdOverride >= 100)
2542         {
2543             RDOQIntraTUThreshold = 65535;
2544         }
2545         else if (m_rdoqIntraTuThresholdOverride > 0)
2546         {
2547             uint32_t frameWidth = (m_hevcSeqParams->wFrameWidthInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3);
2548             uint32_t frameHeight = (m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3);
2549             int32_t frameSize = frameWidth * frameHeight;
2550             RDOQIntraTUThreshold = (((frameSize * m_rdoqIntraTuThreshold) / 100) >> 8);
2551 
2552             uint16_t numPipe = m_numVdbox;
2553             if ((m_hevcPicParams->num_tile_columns_minus1 + 1) > m_numVdbox)
2554             {
2555                 numPipe = 1;
2556             }
2557             if ((m_hevcPicParams->tiles_enabled_flag) && (numPipe > 1))
2558             {
2559                 RDOQIntraTUThreshold /= numPipe;
2560             }
2561             if (RDOQIntraTUThreshold > 65535)
2562             {
2563                 RDOQIntraTUThreshold = 65535;
2564             }
2565         }
2566 
2567         picStateParams.bRDOQIntraTUDisable = m_rdoqIntraTuDisableOverride;
2568         picStateParams.wRDOQIntraTUThreshold = (uint16_t)RDOQIntraTUThreshold;
2569     }
2570 #endif
2571 
2572     picStateParams.currPass = m_currPass;
2573     if (CodecHalIsFeiEncode(m_codecFunction) && m_hevcFeiPicParams && m_hevcFeiPicParams->dwMaxFrameSize)
2574     {
2575         picStateParams.deltaQp = m_hevcFeiPicParams->pDeltaQp;
2576         picStateParams.maxFrameSize = m_hevcFeiPicParams->dwMaxFrameSize;
2577     }
2578 }
2579 
SetBatchBufferForPakSlices()2580 MOS_STATUS CodechalEncodeHevcBase::SetBatchBufferForPakSlices()
2581 {
2582     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2583 
2584     CODECHAL_ENCODE_FUNCTION_ENTER;
2585 
2586     m_useBatchBufferForPakSlices         = m_singleTaskPhaseSupported && m_singleTaskPhaseSupportedInPak;
2587     m_batchBufferForPakSlicesStartOffset = 0;
2588 
2589     if (m_useBatchBufferForPakSlices)
2590     {
2591         if (IsFirstPass())
2592         {
2593             // The same buffer is used for all slices for all passes
2594             uint32_t batchBufferForPakSlicesSize =
2595                 (m_numPasses + 1) * m_numSlices * m_sliceStatesSize;
2596 
2597             CODECHAL_ENCODE_ASSERT(batchBufferForPakSlicesSize);
2598 
2599             if (batchBufferForPakSlicesSize >
2600                 (uint32_t)m_batchBufferForPakSlices[m_currPakSliceIdx].iSize)
2601             {
2602                 if (m_batchBufferForPakSlices[m_currPakSliceIdx].iSize)
2603                 {
2604                     CODECHAL_ENCODE_CHK_STATUS_RETURN(ReleaseBatchBufferForPakSlices(m_currPakSliceIdx));
2605                 }
2606 
2607                 CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBatchBufferForPakSlices(
2608                     m_numSlices,
2609                     m_numPasses));
2610             }
2611         }
2612 
2613         CODECHAL_ENCODE_CHK_STATUS_RETURN(Mhw_LockBb(
2614             m_osInterface,
2615             &m_batchBufferForPakSlices[m_currPakSliceIdx]));
2616         m_batchBufferForPakSlicesStartOffset = IsFirstPass() ? 0 : (uint32_t)m_batchBufferForPakSlices[m_currPakSliceIdx].iCurrent;
2617     }
2618 
2619     return eStatus;
2620 }
2621 
CreateMhwParams()2622 void CodechalEncodeHevcBase::CreateMhwParams()
2623 {
2624     m_sliceStateParams = MOS_New(MHW_VDBOX_HEVC_SLICE_STATE);
2625     m_pipeModeSelectParams = MOS_New(MHW_VDBOX_PIPE_MODE_SELECT_PARAMS);
2626     m_pipeBufAddrParams = MOS_New(MHW_VDBOX_PIPE_BUF_ADDR_PARAMS);
2627 }
2628 
SetHcpSliceStateCommonParams(MHW_VDBOX_HEVC_SLICE_STATE & sliceStateParams)2629 void CodechalEncodeHevcBase::SetHcpSliceStateCommonParams(MHW_VDBOX_HEVC_SLICE_STATE& sliceStateParams)
2630 {
2631     CODECHAL_ENCODE_FUNCTION_ENTER;
2632 
2633     sliceStateParams = {};
2634     sliceStateParams.presDataBuffer = &m_resMbCodeSurface;
2635     sliceStateParams.pHevcPicIdx           = &(m_picIdx[0]);
2636     sliceStateParams.pEncodeHevcSeqParams  = m_hevcSeqParams;
2637     sliceStateParams.pEncodeHevcPicParams  = m_hevcPicParams;
2638     sliceStateParams.pBsBuffer = &m_bsBuffer;
2639     sliceStateParams.ppNalUnitParams       = m_nalUnitParams;
2640     sliceStateParams.bBrcEnabled           = m_brcEnabled;
2641     sliceStateParams.dwHeaderBytesInserted = 0;
2642     sliceStateParams.dwHeaderDummyBytes = 0;
2643     sliceStateParams.pRefIdxMapping        = m_refIdxMapping;
2644     sliceStateParams.bIsLowDelay           = m_lowDelay;
2645     sliceStateParams.RoundingIntra         = m_roundingIntra;
2646     sliceStateParams.RoundingInter         = m_roundingInter;
2647 }
2648 
SetHcpSliceStateParams(MHW_VDBOX_HEVC_SLICE_STATE & sliceStateParams,PCODEC_ENCODER_SLCDATA slcData,uint32_t currSlcIdx)2649 void CodechalEncodeHevcBase::SetHcpSliceStateParams(
2650     MHW_VDBOX_HEVC_SLICE_STATE& sliceStateParams,
2651     PCODEC_ENCODER_SLCDATA slcData,
2652     uint32_t currSlcIdx)
2653 {
2654     CODECHAL_ENCODE_FUNCTION_ENTER;
2655 
2656     sliceStateParams.pEncodeHevcSliceParams    = &m_hevcSliceParams[currSlcIdx];
2657     sliceStateParams.dwDataBufferOffset = slcData[currSlcIdx].CmdOffset;
2658     sliceStateParams.dwOffset = slcData[currSlcIdx].SliceOffset;
2659     sliceStateParams.dwLength = slcData[currSlcIdx].BitSize;
2660     sliceStateParams.uiSkipEmulationCheckCount = slcData[currSlcIdx].SkipEmulationByteCount;
2661     sliceStateParams.dwSliceIndex = currSlcIdx;
2662     sliceStateParams.bLastSlice = (currSlcIdx == m_numSlices - 1);
2663     sliceStateParams.bFirstPass = IsFirstPass();
2664     sliceStateParams.bLastPass = IsLastPass();
2665     sliceStateParams.bInsertBeforeSliceHeaders = (currSlcIdx == 0);
2666     sliceStateParams.bSaoLumaFlag              = (m_hevcSeqParams->SAO_enabled_flag) ? m_hevcSliceParams[currSlcIdx].slice_sao_luma_flag : 0;
2667     sliceStateParams.bSaoChromaFlag            = (m_hevcSeqParams->SAO_enabled_flag) ? m_hevcSliceParams[currSlcIdx].slice_sao_chroma_flag : 0;
2668     sliceStateParams.DeblockingFilterDisable   = m_hevcSliceParams[currSlcIdx].slice_deblocking_filter_disable_flag;
2669     sliceStateParams.TcOffsetDiv2              = m_hevcSliceParams[currSlcIdx].tc_offset_div2;
2670     sliceStateParams.BetaOffsetDiv2            = m_hevcSliceParams[currSlcIdx].beta_offset_div2;
2671 
2672 
2673     if (m_useBatchBufferForPakSlices)
2674     {
2675         sliceStateParams.pBatchBufferForPakSlices =
2676             &m_batchBufferForPakSlices[m_currPakSliceIdx];
2677         sliceStateParams.bSingleTaskPhaseSupported = true;
2678         sliceStateParams.dwBatchBufferForPakSlicesStartOffset = m_batchBufferForPakSlicesStartOffset;
2679     }
2680 
2681     if (m_hevcPicParams->transform_skip_enabled_flag)
2682     {
2683         CalcTransformSkipParameters(sliceStateParams.EncodeHevcTransformSkipParams);
2684     }
2685 }
2686 
AddHcpRefIdxCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_HEVC_SLICE_STATE params)2687 MOS_STATUS CodechalEncodeHevcBase::AddHcpRefIdxCmd(
2688     PMOS_COMMAND_BUFFER cmdBuffer,
2689     PMHW_BATCH_BUFFER batchBuffer,
2690     PMHW_VDBOX_HEVC_SLICE_STATE params)
2691 {
2692     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2693 
2694     CODECHAL_ENCODE_FUNCTION_ENTER;
2695 
2696     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
2697     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeHevcSliceParams);
2698     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeHevcPicParams);
2699 
2700     if (cmdBuffer == nullptr && batchBuffer == nullptr)
2701     {
2702         CODECHAL_ENCODE_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
2703         return MOS_STATUS_NULL_POINTER;
2704     }
2705 
2706     PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams = params->pEncodeHevcPicParams;
2707     PCODEC_HEVC_ENCODE_SLICE_PARAMS hevcSlcParams = params->pEncodeHevcSliceParams;
2708 
2709     if (hevcSlcParams->slice_type != CODECHAL_ENCODE_HEVC_I_SLICE)
2710     {
2711         MHW_VDBOX_HEVC_REF_IDX_PARAMS refIdxParams;
2712 
2713         refIdxParams.CurrPic = hevcPicParams->CurrReconstructedPic;
2714         refIdxParams.isEncode = true;
2715         refIdxParams.ucList = LIST_0;
2716         refIdxParams.ucNumRefForList = hevcSlcParams->num_ref_idx_l0_active_minus1 + 1;
2717         eStatus = MOS_SecureMemcpy(&refIdxParams.RefPicList, sizeof(refIdxParams.RefPicList),
2718             &hevcSlcParams->RefPicList, sizeof(hevcSlcParams->RefPicList));
2719         if (eStatus != MOS_STATUS_SUCCESS)
2720         {
2721             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
2722             return eStatus;
2723         }
2724 
2725         refIdxParams.hevcRefList = (void**)m_refList;
2726         refIdxParams.poc_curr_pic = hevcPicParams->CurrPicOrderCnt;
2727         for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
2728         {
2729             refIdxParams.poc_list[i] = hevcPicParams->RefFramePOCList[i];
2730         }
2731 
2732         refIdxParams.pRefIdxMapping = params->pRefIdxMapping;
2733         refIdxParams.RefFieldPicFlag = 0; // there is no interlaced support in encoder
2734         refIdxParams.RefBottomFieldFlag = 0; // there is no interlaced support in encoder
2735 
2736         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpRefIdxStateCmd(cmdBuffer, batchBuffer, &refIdxParams));
2737 
2738         if (hevcSlcParams->slice_type == CODECHAL_ENCODE_HEVC_B_SLICE)
2739         {
2740             refIdxParams.ucList = LIST_1;
2741             refIdxParams.ucNumRefForList = hevcSlcParams->num_ref_idx_l1_active_minus1 + 1;
2742             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpRefIdxStateCmd(cmdBuffer, batchBuffer, &refIdxParams));
2743         }
2744     }
2745 
2746     return eStatus;
2747 }
2748 
AddHcpPakInsertNALUs(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_HEVC_SLICE_STATE params)2749 MOS_STATUS CodechalEncodeHevcBase::AddHcpPakInsertNALUs(
2750     PMOS_COMMAND_BUFFER cmdBuffer,
2751     PMHW_BATCH_BUFFER batchBuffer,
2752     PMHW_VDBOX_HEVC_SLICE_STATE params)
2753 {
2754     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2755 
2756     CODECHAL_ENCODE_FUNCTION_ENTER;
2757 
2758     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
2759     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
2760     CODECHAL_ENCODE_CHK_NULL_RETURN(params->ppNalUnitParams);
2761 
2762     if (cmdBuffer == nullptr && batchBuffer == nullptr)
2763     {
2764         CODECHAL_ENCODE_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
2765         return MOS_STATUS_NULL_POINTER;
2766     }
2767 
2768     //insert AU, SPS, PSP headers before first slice header
2769     if (params->bInsertBeforeSliceHeaders)
2770     {
2771         uint32_t maxBytesInPakInsertObjCmd = ((2 << 11) - 1) * 4; // 12 bits for Length field in PAK_INSERT_OBJ cmd
2772 
2773         for (auto i = 0; i < HEVC_MAX_NAL_UNIT_TYPE; i++)
2774         {
2775             uint32_t nalunitPosiSize = params->ppNalUnitParams[i]->uiSize;
2776             uint32_t nalunitPosiOffset = params->ppNalUnitParams[i]->uiOffset;
2777 
2778             while (nalunitPosiSize > 0)
2779             {
2780                 uint32_t bitSize = MOS_MIN(maxBytesInPakInsertObjCmd * 8, nalunitPosiSize * 8);
2781                 uint32_t offSet = nalunitPosiOffset;
2782 
2783                 MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams;
2784                 MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams));
2785                 pakInsertObjectParams.bEmulationByteBitsInsert = params->ppNalUnitParams[i]->bInsertEmulationBytes;
2786                 pakInsertObjectParams.uiSkipEmulationCheckCount = params->ppNalUnitParams[i]->uiSkipEmulationCheckCount;
2787                 pakInsertObjectParams.pBsBuffer = params->pBsBuffer;
2788                 pakInsertObjectParams.dwBitSize = bitSize;
2789                 pakInsertObjectParams.dwOffset = offSet;
2790                 pakInsertObjectParams.pBatchBufferForPakSlices = batchBuffer;
2791                 pakInsertObjectParams.bVdencInUse = params->bVdencInUse;
2792 
2793                 if (nalunitPosiSize > maxBytesInPakInsertObjCmd)
2794                 {
2795                     nalunitPosiSize -= maxBytesInPakInsertObjCmd;
2796                     nalunitPosiOffset += maxBytesInPakInsertObjCmd;
2797                 }
2798                 else
2799                 {
2800                     nalunitPosiSize = 0;
2801                 }
2802 
2803                 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPakInsertObject(cmdBuffer, &pakInsertObjectParams));
2804             }
2805         }
2806     }
2807 
2808     return eStatus;
2809 }
2810 
AddHcpPakInsertSliceHeader(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_HEVC_SLICE_STATE params)2811 MOS_STATUS CodechalEncodeHevcBase::AddHcpPakInsertSliceHeader(
2812     PMOS_COMMAND_BUFFER cmdBuffer,
2813     PMHW_BATCH_BUFFER batchBuffer,
2814     PMHW_VDBOX_HEVC_SLICE_STATE params)
2815 {
2816     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2817 
2818     CODECHAL_ENCODE_FUNCTION_ENTER;
2819 
2820     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
2821     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
2822 
2823     if (cmdBuffer == nullptr && batchBuffer == nullptr)
2824     {
2825         CODECHAL_ENCODE_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
2826         return MOS_STATUS_NULL_POINTER;
2827     }
2828 
2829     // Insert slice header
2830     MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams;
2831     MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams));
2832     pakInsertObjectParams.bLastHeader = true;
2833     pakInsertObjectParams.bEmulationByteBitsInsert = true;
2834     pakInsertObjectParams.pBatchBufferForPakSlices = batchBuffer;
2835 
2836     // App does the slice header packing, set the skip count passed by the app
2837     pakInsertObjectParams.uiSkipEmulationCheckCount = params->uiSkipEmulationCheckCount;
2838     pakInsertObjectParams.pBsBuffer = params->pBsBuffer;
2839     pakInsertObjectParams.dwBitSize = params->dwLength;
2840     pakInsertObjectParams.dwOffset = params->dwOffset;
2841     pakInsertObjectParams.bVdencInUse = params->bVdencInUse;
2842 
2843     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPakInsertObject(
2844         cmdBuffer,
2845         &pakInsertObjectParams));
2846 
2847     return eStatus;
2848 }
2849 
CodechalEncodeHevcBase(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)2850 CodechalEncodeHevcBase::CodechalEncodeHevcBase(
2851     CodechalHwInterface* hwInterface,
2852     CodechalDebugInterface* debugInterface,
2853     PCODECHAL_STANDARD_INFO standardInfo)
2854     :CodechalEncoderState(hwInterface, debugInterface, standardInfo)
2855 {
2856     // initialze class members
2857     MOS_ZeroMemory(&m_resDeblockingFilterRowStoreScratchBuffer, sizeof(m_resDeblockingFilterRowStoreScratchBuffer));
2858     MOS_ZeroMemory(&m_resDeblockingFilterTileRowStoreScratchBuffer, sizeof(m_resDeblockingFilterTileRowStoreScratchBuffer));
2859     MOS_ZeroMemory(&m_resDeblockingFilterColumnRowStoreScratchBuffer, sizeof(m_resDeblockingFilterColumnRowStoreScratchBuffer));
2860     MOS_ZeroMemory(&m_resMetadataLineBuffer, sizeof(m_resMetadataLineBuffer));
2861     MOS_ZeroMemory(&m_resMetadataTileLineBuffer, sizeof(m_resMetadataTileLineBuffer));
2862     MOS_ZeroMemory(&m_resMetadataTileColumnBuffer, sizeof(m_resMetadataTileColumnBuffer));
2863     MOS_ZeroMemory(&m_resSaoLineBuffer, sizeof(m_resSaoLineBuffer));
2864     MOS_ZeroMemory(&m_resSaoTileLineBuffer, sizeof(m_resSaoTileLineBuffer));
2865     MOS_ZeroMemory(&m_resSaoTileColumnBuffer, sizeof(m_resSaoTileColumnBuffer));
2866     MOS_ZeroMemory(&m_resLcuBaseAddressBuffer, sizeof(m_resLcuBaseAddressBuffer));
2867     MOS_ZeroMemory(&m_resLcuIldbStreamOutBuffer, sizeof(m_resLcuIldbStreamOutBuffer));
2868     MOS_ZeroMemory(&m_resSaoStreamOutBuffer, sizeof(m_resSaoStreamOutBuffer));
2869     MOS_ZeroMemory(&m_resFrameStatStreamOutBuffer, sizeof(m_resFrameStatStreamOutBuffer));
2870     MOS_ZeroMemory(&m_resSseSrcPixelRowStoreBuffer, sizeof(m_resSseSrcPixelRowStoreBuffer));
2871     MOS_ZeroMemory(m_batchBufferForPakSlices, sizeof(m_batchBufferForPakSlices));
2872 
2873     MOS_ZeroMemory(m_refSync, sizeof(m_refSync));
2874     MOS_ZeroMemory(m_refIdxMapping, sizeof(m_refIdxMapping));
2875 
2876     MOS_ZeroMemory(m_currUsedRefPic, sizeof(m_currUsedRefPic));
2877     ;
2878     MOS_ZeroMemory(m_picIdx, sizeof(m_picIdx));
2879     MOS_ZeroMemory(m_refList, sizeof(m_refList));
2880 
2881     MOS_ZeroMemory(&m_s4XMeMvDataBuffer, sizeof(m_s4XMeMvDataBuffer));
2882     MOS_ZeroMemory(&m_s16XMeMvDataBuffer, sizeof(m_s16XMeMvDataBuffer));
2883     MOS_ZeroMemory(&m_s32XMeMvDataBuffer, sizeof(m_s32XMeMvDataBuffer));
2884     MOS_ZeroMemory(&m_s4XMeDistortionBuffer, sizeof(m_s4XMeDistortionBuffer));
2885     MOS_ZeroMemory(&m_mbQpDataSurface, sizeof(m_mbQpDataSurface));
2886     MOS_ZeroMemory(&m_resPakcuLevelStreamoutData, sizeof(m_resPakcuLevelStreamoutData));
2887 
2888     m_fieldScalingOutputInterleaved = false;
2889     m_interlacedFieldDisabled = true;
2890     m_firstField = true;     // Each frame is treated as the first field
2891 
2892     m_userFeatureKeyReport = true;
2893     m_useCmScalingKernel = true;
2894     m_codecGetStatusReportDefined = true;       // Codec specific GetStatusReport is implemented.
2895 
2896     m_vdboxOneDefaultUsed = true;
2897 }
2898 
CalculatePictureStateCommandSize()2899 MOS_STATUS CodechalEncodeHevcBase::CalculatePictureStateCommandSize()
2900 {
2901     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2902 
2903     CODECHAL_ENCODE_FUNCTION_ENTER;
2904 
2905     MHW_VDBOX_STATE_CMDSIZE_PARAMS stateCmdSizeParams;
2906     CODECHAL_ENCODE_CHK_STATUS_RETURN(
2907         m_hwInterface->GetHxxStateCommandSize(
2908             CODECHAL_ENCODE_MODE_HEVC,
2909             &m_defaultPictureStatesSize,
2910             &m_defaultPicturePatchListSize,
2911             &stateCmdSizeParams));
2912 
2913     return eStatus;
2914 }
2915 
AddHcpPipeBufAddrCmd(PMOS_COMMAND_BUFFER cmdBuffer)2916 MOS_STATUS CodechalEncodeHevcBase::AddHcpPipeBufAddrCmd(
2917     PMOS_COMMAND_BUFFER  cmdBuffer)
2918 {
2919     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2920 
2921     CODECHAL_ENCODE_FUNCTION_ENTER;
2922 
2923     *m_pipeBufAddrParams = {};
2924     SetHcpPipeBufAddrParams(*m_pipeBufAddrParams);
2925 #ifdef _MMC_SUPPORTED
2926     m_mmcState->SetPipeBufAddr(m_pipeBufAddrParams);
2927 #endif
2928     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPipeBufAddrCmd(cmdBuffer, m_pipeBufAddrParams));
2929 
2930     return eStatus;
2931 }
2932 
ComputeTemporalDifferent(CODEC_PICTURE refPic)2933 short CodechalEncodeHevcBase::ComputeTemporalDifferent(CODEC_PICTURE  refPic)
2934 {
2935     short diff_poc = 0;
2936 
2937     if (!CodecHal_PictureIsInvalid(refPic))
2938     {
2939         diff_poc = m_hevcPicParams->CurrPicOrderCnt - m_hevcPicParams->RefFramePOCList[refPic.FrameIdx];
2940 
2941         if (diff_poc < -16)
2942         {
2943             CODECHAL_ENCODE_ASSERTMESSAGE("POC out of range, it will be clipped.");
2944             diff_poc = -16;
2945         }
2946         else
2947             if (diff_poc > 16)
2948             {
2949                 CODECHAL_ENCODE_ASSERTMESSAGE("POC out of range, it will be clipped.");
2950                 diff_poc = 16;
2951             }
2952     }
2953 
2954     return diff_poc;
2955 }
2956 
InitSurfaceCodecParams1D(PCODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams,PMOS_RESOURCE buffer,uint32_t size,uint32_t offset,uint32_t cacheabilityControl,uint32_t bindingTableOffset,bool isWritable)2957 MOS_STATUS CodechalEncodeHevcBase::InitSurfaceCodecParams1D(
2958     PCODECHAL_SURFACE_CODEC_PARAMS  surfaceCodecParams,
2959     PMOS_RESOURCE                   buffer,
2960     uint32_t                        size,
2961     uint32_t                        offset,
2962     uint32_t                        cacheabilityControl,
2963     uint32_t                        bindingTableOffset,
2964     bool                            isWritable)
2965 {
2966     if (surfaceCodecParams == nullptr)
2967     {
2968         return MOS_STATUS_NULL_POINTER;
2969     }
2970 
2971     MOS_ZeroMemory(surfaceCodecParams, sizeof(*surfaceCodecParams));
2972     surfaceCodecParams->presBuffer = buffer;
2973     surfaceCodecParams->dwSize = size;
2974     surfaceCodecParams->dwOffset = offset;
2975     surfaceCodecParams->dwCacheabilityControl = cacheabilityControl;
2976     surfaceCodecParams->dwBindingTableOffset = bindingTableOffset;
2977     surfaceCodecParams->bIsWritable =
2978         surfaceCodecParams->bRenderTarget = isWritable;
2979 
2980     return MOS_STATUS_SUCCESS;
2981 }
2982 
InitSurfaceCodecParams2D(PCODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams,PMOS_SURFACE surface,uint32_t cacheabilityControl,uint32_t bindingTableOffset,uint32_t verticalLineStride,bool isWritable)2983 MOS_STATUS CodechalEncodeHevcBase::InitSurfaceCodecParams2D(
2984     PCODECHAL_SURFACE_CODEC_PARAMS  surfaceCodecParams,
2985     PMOS_SURFACE                    surface,
2986     uint32_t                        cacheabilityControl,
2987     uint32_t                        bindingTableOffset,
2988     uint32_t                        verticalLineStride,
2989     bool                            isWritable)
2990 {
2991     if (surfaceCodecParams == nullptr)
2992     {
2993         return MOS_STATUS_NULL_POINTER;
2994     }
2995 
2996     MOS_ZeroMemory(surfaceCodecParams, sizeof(*surfaceCodecParams));
2997     surfaceCodecParams->bIs2DSurface = true;
2998     surfaceCodecParams->bMediaBlockRW = true; // Use media block RW for DP 2D surface access
2999     surfaceCodecParams->psSurface = surface;
3000     surfaceCodecParams->dwCacheabilityControl = cacheabilityControl;
3001     surfaceCodecParams->dwBindingTableOffset = bindingTableOffset;
3002     surfaceCodecParams->dwVerticalLineStride = verticalLineStride;
3003     surfaceCodecParams->bIsWritable =
3004         surfaceCodecParams->bRenderTarget = isWritable;
3005 
3006     return MOS_STATUS_SUCCESS;
3007 }
3008 
AllocateResources4xME(HmeParams * param)3009 MOS_STATUS CodechalEncodeHevcBase::AllocateResources4xME(
3010     HmeParams *param)
3011 {
3012     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
3013 
3014     CODECHAL_ENCODE_FUNCTION_ENTER;
3015 
3016     CODECHAL_ENCODE_CHK_NULL_RETURN(param);
3017 
3018     if (!m_encEnabled || !m_hmeSupported)
3019     {
3020         return eStatus;
3021     }
3022 
3023     MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
3024     MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
3025     allocParamsForBuffer2D.Type     = MOS_GFXRES_2D;
3026     allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
3027     allocParamsForBuffer2D.Format   = Format_Buffer_2D;
3028 
3029     MOS_ZeroMemory(param->ps4xMeMvDataBuffer, sizeof(MOS_SURFACE));
3030     param->ps4xMeMvDataBuffer->TileType      = MOS_TILE_LINEAR;
3031     param->ps4xMeMvDataBuffer->bArraySpacing = true;
3032     param->ps4xMeMvDataBuffer->Format        = Format_Buffer_2D;
3033     param->ps4xMeMvDataBuffer->dwWidth       = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64); // MediaBlockRW requires pitch multiple of 64 bytes when linear.
3034     param->ps4xMeMvDataBuffer->dwHeight      = (m_downscaledHeightInMb4x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
3035     param->ps4xMeMvDataBuffer->dwPitch       = param->ps4xMeMvDataBuffer->dwWidth;
3036 
3037     allocParamsForBuffer2D.dwWidth  = param->ps4xMeMvDataBuffer->dwWidth;
3038     allocParamsForBuffer2D.dwHeight = param->ps4xMeMvDataBuffer->dwHeight;
3039     allocParamsForBuffer2D.pBufName = "4xME MV Data Buffer";
3040 
3041     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
3042         m_osInterface,
3043         &allocParamsForBuffer2D,
3044         &param->ps4xMeMvDataBuffer->OsResource);
3045 
3046     if (eStatus != MOS_STATUS_SUCCESS)
3047     {
3048         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate 4xME MV Data Buffer.");
3049         return eStatus;
3050     }
3051 
3052     CleanUpResource(&param->ps4xMeMvDataBuffer->OsResource, &allocParamsForBuffer2D);
3053 
3054     if (param->b4xMeDistortionBufferSupported)
3055     {
3056         uint32_t ajustedHeight =
3057             m_downscaledHeightInMb4x * CODECHAL_MACROBLOCK_HEIGHT * SCALE_FACTOR_4x;
3058         uint32_t downscaledFieldHeightInMB4x =
3059             CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(((ajustedHeight + 1) >> 1) / 4);
3060 
3061         MOS_ZeroMemory(param->ps4xMeDistortionBuffer, sizeof(MOS_SURFACE));
3062         param->ps4xMeDistortionBuffer->TileType      = MOS_TILE_LINEAR;
3063         param->ps4xMeDistortionBuffer->bArraySpacing = true;
3064         param->ps4xMeDistortionBuffer->Format        = Format_Buffer_2D;
3065         param->ps4xMeDistortionBuffer->dwWidth       = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64);
3066         param->ps4xMeDistortionBuffer->dwHeight      = 2 * MOS_ALIGN_CEIL((downscaledFieldHeightInMB4x * 4 * 10), 8);
3067         param->ps4xMeDistortionBuffer->dwPitch       = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64);
3068 
3069         allocParamsForBuffer2D.dwWidth  = param->ps4xMeDistortionBuffer->dwWidth;
3070         allocParamsForBuffer2D.dwHeight = param->ps4xMeDistortionBuffer->dwHeight;
3071         allocParamsForBuffer2D.pBufName = "4xME Distortion Buffer";
3072 
3073         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
3074             m_osInterface,
3075             &allocParamsForBuffer2D,
3076             &param->ps4xMeDistortionBuffer->OsResource);
3077 
3078         if (eStatus != MOS_STATUS_SUCCESS)
3079         {
3080             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate 4xME Distortion Buffer.");
3081             return eStatus;
3082         }
3083         CleanUpResource(&param->ps4xMeDistortionBuffer->OsResource, &allocParamsForBuffer2D);
3084     }
3085 
3086     return eStatus;
3087 }
3088 
AllocateResources16xME(HmeParams * param)3089 MOS_STATUS CodechalEncodeHevcBase::AllocateResources16xME(
3090     HmeParams  *param)
3091 {
3092     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
3093 
3094     CODECHAL_ENCODE_FUNCTION_ENTER;
3095 
3096     CODECHAL_ENCODE_CHK_NULL_RETURN(param);
3097 
3098     if (!m_encEnabled || !m_hmeSupported)
3099     {
3100         return eStatus;
3101     }
3102 
3103     MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
3104     MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
3105     allocParamsForBuffer2D.Type     = MOS_GFXRES_2D;
3106     allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
3107     allocParamsForBuffer2D.Format   = Format_Buffer_2D;
3108 
3109     if (m_16xMeSupported)
3110     {
3111         MOS_ZeroMemory(param->ps16xMeMvDataBuffer, sizeof(MOS_SURFACE));
3112         param->ps16xMeMvDataBuffer->TileType      = MOS_TILE_LINEAR;
3113         param->ps16xMeMvDataBuffer->bArraySpacing = true;
3114         param->ps16xMeMvDataBuffer->Format        = Format_Buffer_2D;
3115         param->ps16xMeMvDataBuffer->dwWidth       = MOS_ALIGN_CEIL((m_downscaledWidthInMb16x * 32), 64); // MediaBlockRW requires pitch multiple of 64 bytes when linear
3116         param->ps16xMeMvDataBuffer->dwHeight      = (m_downscaledHeightInMb16x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
3117         param->ps16xMeMvDataBuffer->dwPitch       = param->ps16xMeMvDataBuffer->dwWidth;
3118 
3119         allocParamsForBuffer2D.dwWidth  = param->ps16xMeMvDataBuffer->dwWidth;
3120         allocParamsForBuffer2D.dwHeight = param->ps16xMeMvDataBuffer->dwHeight;
3121         allocParamsForBuffer2D.pBufName = "16xME MV Data Buffer";
3122 
3123         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
3124             m_osInterface,
3125             &allocParamsForBuffer2D,
3126             &param->ps16xMeMvDataBuffer->OsResource);
3127 
3128         if (eStatus != MOS_STATUS_SUCCESS)
3129         {
3130             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate 16xME MV Data Buffer.");
3131             return eStatus;
3132         }
3133         CleanUpResource(&param->ps16xMeMvDataBuffer->OsResource, &allocParamsForBuffer2D);
3134     }
3135 
3136     return eStatus;
3137 }
3138 
AllocateResources32xME(HmeParams * param)3139 MOS_STATUS CodechalEncodeHevcBase::AllocateResources32xME(
3140     HmeParams  *param)
3141 {
3142     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
3143 
3144     CODECHAL_ENCODE_FUNCTION_ENTER;
3145 
3146     CODECHAL_ENCODE_CHK_NULL_RETURN(param);
3147 
3148     if (!m_encEnabled || !m_hmeSupported)
3149     {
3150         return eStatus;
3151     }
3152 
3153     MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
3154     MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
3155     allocParamsForBuffer2D.Type     = MOS_GFXRES_2D;
3156     allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
3157     allocParamsForBuffer2D.Format   = Format_Buffer_2D;
3158 
3159     if (m_32xMeSupported)
3160     {
3161         MOS_ZeroMemory(param->ps32xMeMvDataBuffer, sizeof(MOS_SURFACE));
3162         param->ps32xMeMvDataBuffer->TileType      = MOS_TILE_LINEAR;
3163         param->ps32xMeMvDataBuffer->bArraySpacing = true;
3164         param->ps32xMeMvDataBuffer->Format        = Format_Buffer_2D;
3165         param->ps32xMeMvDataBuffer->dwWidth       = MOS_ALIGN_CEIL((m_downscaledWidthInMb32x * 32), 64); // MediaBlockRW requires pitch multiple of 64 bytes when linear
3166         param->ps32xMeMvDataBuffer->dwHeight      = (m_downscaledHeightInMb32x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
3167         param->ps32xMeMvDataBuffer->dwPitch       = param->ps32xMeMvDataBuffer->dwWidth;
3168 
3169         allocParamsForBuffer2D.dwWidth  = param->ps32xMeMvDataBuffer->dwWidth;
3170         allocParamsForBuffer2D.dwHeight = param->ps32xMeMvDataBuffer->dwHeight;
3171         allocParamsForBuffer2D.pBufName = "32xME MV Data Buffer";
3172 
3173         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
3174             m_osInterface,
3175             &allocParamsForBuffer2D,
3176             &param->ps32xMeMvDataBuffer->OsResource);
3177 
3178         if (eStatus != MOS_STATUS_SUCCESS)
3179         {
3180             CODECHAL_ENCODE_ASSERTMESSAGE("%s: Failed to allocate 32xME MV Data Buffer\n", __FUNCTION__);
3181             return eStatus;
3182         }
3183         CleanUpResource(&param->ps32xMeMvDataBuffer->OsResource, &allocParamsForBuffer2D);
3184     }
3185 
3186     return eStatus;
3187 }
3188 
DestroyMEResources(HmeParams * param)3189 MOS_STATUS CodechalEncodeHevcBase::DestroyMEResources(
3190     HmeParams *param)
3191 {
3192     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
3193 
3194     CODECHAL_ENCODE_FUNCTION_ENTER;
3195 
3196     CODECHAL_ENCODE_CHK_NULL_RETURN(param);
3197 
3198     if (nullptr != param->ps16xMeMvDataBuffer)
3199     {
3200         m_osInterface->pfnFreeResource(
3201             m_osInterface,
3202             &param->ps16xMeMvDataBuffer->OsResource);
3203     }
3204 
3205     if (nullptr != param->ps32xMeMvDataBuffer)
3206     {
3207         m_osInterface->pfnFreeResource(
3208             m_osInterface,
3209             &param->ps32xMeMvDataBuffer->OsResource);
3210     }
3211 
3212     if (nullptr != param->ps4xMeDistortionBuffer)
3213     {
3214         m_osInterface->pfnFreeResource(
3215             m_osInterface,
3216             &param->ps4xMeDistortionBuffer->OsResource);
3217     }
3218 
3219     if (nullptr != param->ps4xMeMvDataBuffer)
3220     {
3221         m_osInterface->pfnFreeResource(
3222             m_osInterface,
3223             &param->ps4xMeMvDataBuffer->OsResource);
3224     }
3225 
3226     if (nullptr != param->presMvAndDistortionSumSurface)
3227     {
3228         m_osInterface->pfnFreeResource(
3229             m_osInterface,
3230             param->presMvAndDistortionSumSurface);
3231     }
3232 
3233     return eStatus;
3234 }
3235 
MotionEstimationDisableCheck()3236 void CodechalEncodeHevcBase::MotionEstimationDisableCheck()
3237 {
3238     CODECHAL_ENCODE_FUNCTION_ENTER;
3239 
3240     if (m_downscaledWidth4x < m_minScaledDimension || m_downscaledWidthInMb4x < m_minScaledDimensionInMb ||
3241         m_downscaledHeight4x < m_minScaledDimension || m_downscaledHeightInMb4x < m_minScaledDimensionInMb)
3242     {
3243         if (m_downscaledWidth4x < m_minScaledDimension || m_downscaledWidthInMb4x < m_minScaledDimensionInMb)
3244         {
3245             m_downscaledWidth4x = m_minScaledDimension;
3246             m_downscaledWidthInMb4x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth4x);
3247         }
3248         if (m_downscaledHeight4x < m_minScaledDimension || m_downscaledHeightInMb4x < m_minScaledDimensionInMb)
3249         {
3250             m_downscaledHeight4x = m_minScaledDimension;
3251             m_downscaledHeightInMb4x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight4x);
3252         }
3253     }
3254 
3255     if (m_downscaledWidth16x < m_minScaledDimension || m_downscaledWidthInMb16x < m_minScaledDimensionInMb ||
3256         m_downscaledHeight16x < m_minScaledDimension || m_downscaledHeightInMb16x < m_minScaledDimensionInMb)
3257     {
3258         if (m_downscaledWidth16x < m_minScaledDimension || m_downscaledWidthInMb16x < m_minScaledDimensionInMb)
3259         {
3260             m_downscaledWidth16x = m_minScaledDimension;
3261             m_downscaledWidthInMb16x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth16x);
3262         }
3263         if (m_downscaledHeight16x < m_minScaledDimension || m_downscaledHeightInMb16x < m_minScaledDimensionInMb)
3264         {
3265             m_downscaledHeight16x = m_minScaledDimension;
3266             m_downscaledHeightInMb16x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight16x);
3267         }
3268     }
3269 
3270     if (m_downscaledWidth32x < m_minScaledDimension || m_downscaledWidthInMb32x < m_minScaledDimensionInMb)
3271     {
3272         m_downscaledWidth32x = m_minScaledDimension;
3273         m_downscaledWidthInMb32x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth32x);
3274     }
3275     if (m_downscaledHeight32x < m_minScaledDimension || m_downscaledHeightInMb32x < m_minScaledDimensionInMb)
3276     {
3277         m_downscaledHeight32x = m_minScaledDimension;
3278         m_downscaledHeightInMb32x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight32x);
3279     }
3280 
3281 }
3282 
ExecuteKernelFunctions()3283 MOS_STATUS CodechalEncodeHevcBase::ExecuteKernelFunctions()
3284 {
3285     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
3286 
3287     CODECHAL_ENCODE_FUNCTION_ENTER;
3288 
3289     CODECHAL_ENCODE_CHK_STATUS_RETURN(EncodeKernelFunctions());
3290 
3291     return eStatus;
3292 }
3293 
3294 #if USE_CODECHAL_DEBUG_TOOL
DumpSeqParams(PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS seqParams)3295 MOS_STATUS CodechalEncodeHevcBase::DumpSeqParams(
3296     PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS seqParams)
3297 {
3298     CODECHAL_DEBUG_FUNCTION_ENTER;
3299 
3300     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSeqParams))
3301     {
3302         return MOS_STATUS_SUCCESS;
3303     }
3304 
3305     CODECHAL_DEBUG_CHK_NULL(seqParams);
3306 
3307     std::ostringstream oss;
3308     oss.setf(std::ios::showbase | std::ios::uppercase);
3309 
3310     oss << "# DDI Parameters:" << std::endl;
3311     oss << "wFrameWidthInMinCbMinus1 = " << +seqParams->wFrameWidthInMinCbMinus1 << std::endl;
3312     oss << "wFrameHeightInMinCbMinus1 = " << +seqParams->wFrameHeightInMinCbMinus1 << std::endl;
3313     oss << "general_profile_idc = " << +seqParams->general_profile_idc << std::endl;
3314     oss << "Level = " << +seqParams->Level << std::endl;
3315     oss << "general_tier_flag = " << +seqParams->general_tier_flag << std::endl;
3316     oss << "GopPicSize = " << +seqParams->GopPicSize << std::endl;
3317     oss << "GopRefDist = " << +seqParams->GopRefDist << std::endl;
3318     oss << "GopOptFlag = " << +seqParams->GopOptFlag << std::endl;
3319     oss << "TargetUsage = " << +seqParams->TargetUsage << std::endl;
3320     oss << "RateControlMethod = " << +seqParams->RateControlMethod << std::endl;
3321     oss << "TargetBitRate = " << +seqParams->TargetBitRate << std::endl;
3322     oss << "MaxBitRate = " << +seqParams->MaxBitRate << std::endl;
3323     oss << "MinBitRate = " << +seqParams->MinBitRate << std::endl;
3324     oss << "FramesRate.Numerator = " << +seqParams->FrameRate.Numerator << std::endl;
3325     oss << "FramesRate.Denominator = " << +seqParams->FrameRate.Denominator << std::endl;
3326     oss << "InitVBVBufferFullnessInBit = " << +seqParams->InitVBVBufferFullnessInBit << std::endl;
3327     oss << "VBVBufferSizeInBit = " << +seqParams->VBVBufferSizeInBit << std::endl;
3328     oss << "bResetBRC = " << +seqParams->bResetBRC << std::endl;
3329     oss << "GlobalSearch = " << +seqParams->GlobalSearch << std::endl;
3330     oss << "LocalSearch = " << +seqParams->LocalSearch << std::endl;
3331     oss << "EarlySkip = " << +seqParams->EarlySkip << std::endl;
3332     oss << "MBBRC = " << +seqParams->MBBRC << std::endl;
3333     oss << "ParallelBRC = " << +seqParams->ParallelBRC << std::endl;
3334     oss << "SliceSizeControl = " << +seqParams->SliceSizeControl << std::endl;
3335     oss << "SourceFormat = " << +seqParams->SourceFormat << std::endl;
3336     oss << "SourceBitDepth = " << +seqParams->SourceBitDepth << std::endl;
3337     oss << "QpAdjustment = " << +seqParams->QpAdjustment << std::endl;
3338     oss << "ROIValueInDeltaQP = " << +seqParams->ROIValueInDeltaQP << std::endl;
3339     oss << "BlockQPforNonRectROI = " << +seqParams->BlockQPforNonRectROI << std::endl;
3340     oss << "EnableTileBasedEncode = " << +seqParams->EnableTileBasedEncode << std::endl;
3341     oss << "bAutoMaxPBFrameSizeForSceneChange = " << +seqParams->bAutoMaxPBFrameSizeForSceneChange << std::endl;
3342     oss << "EnableStreamingBufferLLC = " << +seqParams->EnableStreamingBufferLLC << std::endl;
3343     oss << "EnableStreamingBufferDDR  = " << +seqParams->EnableStreamingBufferDDR << std::endl;
3344     oss << "LowDelayMode = " << +seqParams->LowDelayMode << std::endl;
3345     oss << "DisableHRDConformance = " << +seqParams->DisableHRDConformance << std::endl;
3346     oss << "HierarchicalFlag = " << +seqParams->HierarchicalFlag << std::endl;
3347     oss << "UserMaxIFrameSize = " << +seqParams->UserMaxIFrameSize << std::endl;
3348     oss << "UserMaxPBFrameSize = " << +seqParams->UserMaxPBFrameSize << std::endl;
3349     oss << "ICQQualityFactor = " << +seqParams->ICQQualityFactor << std::endl;
3350     oss << "NumB = " << +seqParams->NumOfBInGop[0] << std::endl;
3351     oss << "NumB1 = " << +seqParams->NumOfBInGop[1] << std::endl;
3352     oss << "NumB2 = " << +seqParams->NumOfBInGop[2] << std::endl;
3353     oss << "UserMaxIFrameSize = " << +seqParams->UserMaxIFrameSize << std::endl;
3354     oss << "UserMaxPBFrameSize = " << +seqParams->UserMaxPBFrameSize << std::endl;
3355     oss << "ICQQualityFactor = " << +seqParams->ICQQualityFactor << std::endl;
3356     oss << "scaling_list_enable_flag = " << +seqParams->scaling_list_enable_flag << std::endl;
3357     oss << "sps_temporal_mvp_enable_flag = " << +seqParams->sps_temporal_mvp_enable_flag << std::endl;
3358     oss << "strong_intra_smoothing_enable_flag = " << +seqParams->strong_intra_smoothing_enable_flag << std::endl;
3359     oss << "amp_enabled_flag = " << +seqParams->amp_enabled_flag << std::endl;
3360     oss << "SAO_enabled_flag = " << +seqParams->SAO_enabled_flag << std::endl;
3361     oss << "pcm_enabled_flag = " << +seqParams->pcm_enabled_flag << std::endl;
3362     oss << "pcm_loop_filter_disable_flag = " << +seqParams->pcm_loop_filter_disable_flag << std::endl;
3363     oss << "chroma_format_idc = " << +seqParams->chroma_format_idc << std::endl;
3364     oss << "separate_colour_plane_flag = " << +seqParams->separate_colour_plane_flag << std::endl;
3365     oss << "palette_mode_enabled_flag = " << +seqParams->palette_mode_enabled_flag << std::endl;
3366     oss << "RGBEncodingEnable = " << +seqParams->RGBEncodingEnable << std::endl;
3367     oss << "PrimaryChannelForRGBEncoding = " << +seqParams->PrimaryChannelForRGBEncoding << std::endl;
3368     oss << "SecondaryChannelForRGBEncoding = " << +seqParams->SecondaryChannelForRGBEncoding << std::endl;
3369 
3370     oss << "log2_max_coding_block_size_minus3 = " << +seqParams->log2_max_coding_block_size_minus3 << std::endl;
3371     oss << "log2_min_coding_block_size_minus3 = " << +seqParams->log2_min_coding_block_size_minus3 << std::endl;
3372     oss << "log2_max_transform_block_size_minus2 = " << +seqParams->log2_max_transform_block_size_minus2 << std::endl;
3373     oss << "log2_min_transform_block_size_minus2 = " << +seqParams->log2_min_transform_block_size_minus2 << std::endl;
3374     oss << "max_transform_hierarchy_depth_intra = " << +seqParams->max_transform_hierarchy_depth_intra << std::endl;
3375     oss << "max_transform_hierarchy_depth_inter = " << +seqParams->max_transform_hierarchy_depth_inter << std::endl;
3376     oss << "log2_min_PCM_cb_size_minus3 = " << +seqParams->log2_min_PCM_cb_size_minus3 << std::endl;
3377     oss << "log2_max_PCM_cb_size_minus3 = " << +seqParams->log2_max_PCM_cb_size_minus3 << std::endl;
3378     oss << "bit_depth_luma_minus8 = " << +seqParams->bit_depth_luma_minus8 << std::endl;
3379     oss << "bit_depth_chroma_minus8 = " << +seqParams->bit_depth_chroma_minus8 << std::endl;
3380     oss << "pcm_sample_bit_depth_luma_minus1 = " << +seqParams->pcm_sample_bit_depth_luma_minus1 << std::endl;
3381     oss << "pcm_sample_bit_depth_chroma_minus1 = " << +seqParams->pcm_sample_bit_depth_chroma_minus1 << std::endl;
3382     oss << "Video Surveillance Mode = " << +seqParams->bVideoSurveillance << std::endl;
3383     oss << "Frame Size Tolerance = " << +seqParams->FrameSizeTolerance << std::endl;
3384     oss << "Look Ahead Depth = " << +seqParams->LookaheadDepth << std::endl;
3385 
3386     const char *fileName = m_debugInterface->CreateFileName(
3387         "_DDIEnc",
3388         CodechalDbgBufferType::bufSeqParams,
3389         CodechalDbgExtType::txt);
3390 
3391     std::ofstream ofs(fileName, std::ios::out);
3392     ofs << oss.str();
3393     ofs.close();
3394 
3395     if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump))
3396     {
3397         if (!m_debugInterface->m_ddiFileName.empty())
3398         {
3399             std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app);
3400             ofs << "SeqParamFile"
3401                 << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl;
3402             ofs.close();
3403         }
3404     }
3405 
3406     return MOS_STATUS_SUCCESS;
3407 }
3408 
DumpPicParams(PCODEC_HEVC_ENCODE_PICTURE_PARAMS picParams)3409 MOS_STATUS CodechalEncodeHevcBase::DumpPicParams(
3410     PCODEC_HEVC_ENCODE_PICTURE_PARAMS picParams)
3411 {
3412     CODECHAL_DEBUG_FUNCTION_ENTER;
3413 
3414     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams))
3415     {
3416         return MOS_STATUS_SUCCESS;
3417     }
3418 
3419     CODECHAL_DEBUG_CHK_NULL(picParams);
3420 
3421     std::ostringstream oss;
3422     oss.setf(std::ios::showbase | std::ios::uppercase);
3423 
3424     oss << "# DDI Parameters:" << std::endl;
3425     oss << "CurrOriginalPic = " << +picParams->CurrOriginalPic.FrameIdx << std::endl;
3426     oss << "CurrReconstructedPic = " << +picParams->CurrReconstructedPic.FrameIdx << std::endl;
3427     oss << "CollocatedRefPicIndex = " << +picParams->CollocatedRefPicIndex << std::endl;
3428 
3429     for (uint16_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; ++i)
3430     {
3431         oss << "RefFrameList[" << +i << "] = " << +picParams->RefFrameList[i].FrameIdx << std::endl;
3432     }
3433 
3434     oss << "CurrPicOrderCnt = " << +picParams->CurrPicOrderCnt << std::endl;
3435 
3436     for (uint16_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; ++i)
3437     {
3438         oss << "RefFramePOCList[" << +i << "] = " << +picParams->RefFramePOCList[i] << std::endl;
3439     }
3440 
3441     oss << "CodingType = " << +picParams->CodingType << std::endl;
3442     oss << "HierarchLevelPlus1 = " << +picParams->HierarchLevelPlus1 << std::endl;
3443     oss << "NumSlices = " << +picParams->NumSlices << std::endl;
3444     oss << "tiles_enabled_flag = " << +picParams->tiles_enabled_flag << std::endl;
3445 
3446     if (picParams->tiles_enabled_flag)
3447     {
3448         oss << "num_tile_columns = " << +picParams->num_tile_columns_minus1 + 1 << std::endl;
3449         for (uint32_t i = 0; i <= picParams->num_tile_columns_minus1; i++)
3450         {
3451             oss << "tile_column_width[" << +i << "] = " << +picParams->tile_column_width[i] << std::endl;
3452         }
3453         oss << "num_tile_rows = " << +picParams->num_tile_rows_minus1 + 1 << std::endl;
3454         for (uint32_t i = 0; i <= picParams->num_tile_rows_minus1; i++)
3455         {
3456             oss << "tile_row_height[" << +i << "] = " << +picParams->tile_row_height[i] << std::endl;
3457         }
3458     }
3459 
3460     oss << "entropy_coding_sync_enabled_flag = " << +picParams->entropy_coding_sync_enabled_flag << std::endl;
3461     oss << "sign_data_hiding_flag = " << +picParams->sign_data_hiding_flag << std::endl;
3462     oss << "constrained_intra_pred_flag = " << +picParams->constrained_intra_pred_flag << std::endl;
3463     oss << "transform_skip_enabled_flag = " << +picParams->transform_skip_enabled_flag << std::endl;
3464     oss << "transquant_bypass_enabled_flag = " << +picParams->transquant_bypass_enabled_flag << std::endl;
3465     oss << "cu_qp_delta_enabled_flag = " << +picParams->cu_qp_delta_enabled_flag << std::endl;
3466     oss << "weighted_pred_flag = " << +picParams->weighted_pred_flag << std::endl;
3467     oss << "weighted_bipred_flag = " << +picParams->weighted_bipred_flag << std::endl;
3468     oss << "bEnableGPUWeightedPrediction = " << +picParams->bEnableGPUWeightedPrediction << std::endl;
3469     oss << "loop_filter_across_slices_flag = " << +picParams->loop_filter_across_slices_flag << std::endl;
3470     oss << "loop_filter_across_tiles_flag = " << +picParams->loop_filter_across_tiles_flag << std::endl;
3471     oss << "scaling_list_data_present_flag = " << +picParams->scaling_list_data_present_flag << std::endl;
3472     oss << "dependent_slice_segments_enabled_flag = " << +picParams->dependent_slice_segments_enabled_flag << std::endl;
3473     oss << "bLastPicInSeq = " << +picParams->bLastPicInSeq << std::endl;
3474     oss << "bLastPicInStream = " << +picParams->bLastPicInStream << std::endl;
3475     oss << "bUseRawPicForRef = " << +picParams->bUseRawPicForRef << std::endl;
3476     oss << "bEmulationByteInsertion = " << +picParams->bEmulationByteInsertion << std::endl;
3477     oss << "bEnableRollingIntraRefresh = " << +picParams->bEnableRollingIntraRefresh << std::endl;
3478     oss << "BRCPrecision = " << +picParams->BRCPrecision << std::endl;
3479     oss << "bScreenContent = " << +picParams->bScreenContent << std::endl;
3480     oss << "QpY = " << +picParams->QpY << std::endl;
3481     oss << "diff_cu_qp_delta_depth = " << +picParams->diff_cu_qp_delta_depth << std::endl;
3482     oss << "pps_cb_qp_offset = " << +picParams->pps_cb_qp_offset << std::endl;
3483     oss << "pps_cr_qp_offset = " << +picParams->pps_cr_qp_offset << std::endl;
3484     oss << "num_tile_columns_minus1 = " << +picParams->num_tile_columns_minus1 << std::endl;
3485     oss << "num_tile_rows_minus1 = " << +picParams->num_tile_rows_minus1 << std::endl;
3486     oss << "log2_parallel_merge_level_minus2 = " << +picParams->log2_parallel_merge_level_minus2 << std::endl;
3487     oss << "num_ref_idx_l0_default_active_minus1 = " << +picParams->num_ref_idx_l0_default_active_minus1 << std::endl;
3488     oss << "num_ref_idx_l1_default_active_minus1 = " << +picParams->num_ref_idx_l1_default_active_minus1 << std::endl;
3489     oss << "LcuMaxBitsizeAllowed = " << +picParams->LcuMaxBitsizeAllowed << std::endl;
3490     oss << "IntraInsertionLocation = " << +picParams->IntraInsertionLocation << std::endl;
3491     oss << "IntraInsertionSize = " << +picParams->IntraInsertionSize << std::endl;
3492     oss << "QpDeltaForInsertedIntra = " << +picParams->QpDeltaForInsertedIntra << std::endl;
3493     oss << "StatusReportFeedbackNumber = " << +picParams->StatusReportFeedbackNumber << std::endl;
3494     oss << "slice_pic_parameter_set_id = " << +picParams->slice_pic_parameter_set_id << std::endl;
3495     oss << "nal_unit_type = " << +picParams->nal_unit_type << std::endl;
3496     oss << "MaxSliceSizeInBytes = " << +picParams->MaxSliceSizeInBytes << std::endl;
3497     oss << "NumROI = " << +picParams->NumROI << std::endl;
3498 
3499     for (uint8_t i = 0; i < 16; ++i)
3500     {
3501         oss << "ROI[" << +i << "] = ";
3502         oss << picParams->ROI[i].Top << " ";
3503         oss << picParams->ROI[i].Bottom << " ";
3504         oss << picParams->ROI[i].Left << " ";
3505         oss << picParams->ROI[i].Right << " ";
3506         oss << picParams->ROI[i].PriorityLevelOrDQp << std::endl;
3507     }
3508     oss << "MaxDeltaQp = " << +picParams->MaxDeltaQp << std::endl;
3509     oss << "MinDeltaQp = " << +picParams->MinDeltaQp << std::endl;
3510     oss << "NumDirtyRects = " << +picParams->NumDirtyRects << std::endl;
3511 
3512     if ((picParams->NumDirtyRects > 0) && picParams->pDirtyRect)
3513     {
3514         for (uint16_t i = 0; i < picParams->NumDirtyRects; i++)
3515         {
3516             oss << "pDirtyRect[" << +i << "].Bottom = " << +picParams->pDirtyRect[i].Bottom << std::endl;
3517             oss << "pDirtyRect[" << +i << "].Top = " << +picParams->pDirtyRect[i].Top << std::endl;
3518             oss << "pDirtyRect[" << +i << "].Left = " << +picParams->pDirtyRect[i].Left << std::endl;
3519             oss << "pDirtyRect[" << +i << "].Right = " << +picParams->pDirtyRect[i].Right << std::endl;
3520         }
3521     }
3522 
3523     oss << "TargetFrameSize = " << +picParams->TargetFrameSize << std::endl;
3524 
3525     const char *fileName = m_debugInterface->CreateFileName(
3526         "_DDIEnc",
3527         CodechalDbgBufferType::bufPicParams,
3528         CodechalDbgExtType::txt);
3529 
3530     std::ofstream ofs(fileName, std::ios::out);
3531     ofs << oss.str();
3532     ofs.close();
3533 
3534     if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump))
3535     {
3536         if (!m_debugInterface->m_ddiFileName.empty())
3537         {
3538             std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app);
3539             ofs << "PicNum"
3540                 << " = \"" << m_debugInterface->m_bufferDumpFrameNum << "\"" << std::endl;
3541             ofs << "PicParamFile"
3542                 << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl;
3543             ofs.close();
3544         }
3545     }
3546 
3547     return MOS_STATUS_SUCCESS;
3548 }
3549 
DumpFeiPicParams(CodecEncodeHevcFeiPicParams * feiPicParams)3550 MOS_STATUS CodechalEncodeHevcBase::DumpFeiPicParams(
3551     CodecEncodeHevcFeiPicParams *feiPicParams)
3552 {
3553     CODECHAL_DEBUG_FUNCTION_ENTER;
3554 
3555     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrFeiPicParams))
3556     {
3557         return MOS_STATUS_SUCCESS;
3558     }
3559 
3560     CODECHAL_DEBUG_CHK_NULL(feiPicParams);
3561 
3562     std::ostringstream oss;
3563     oss.setf(std::ios::showbase | std::ios::uppercase);
3564 
3565     oss << "# DDI Parameters:" << std::endl;
3566     oss << "NumMVPredictorsL0 = " << +feiPicParams->NumMVPredictorsL0 << std::endl;
3567     oss << "NumMVPredictorsL1 = " << +feiPicParams->NumMVPredictorsL1 << std::endl;
3568     oss << "bCTBCmdCuRecordEnable = " << +feiPicParams->bCTBCmdCuRecordEnable << std::endl;
3569     oss << "bDistortionEnable = " << +feiPicParams->bDistortionEnable << std::endl;
3570     oss << "SearchPath = " << +feiPicParams->SearchPath << std::endl;
3571     oss << "LenSP = " << +feiPicParams->LenSP << std::endl;
3572     oss << "MultiPredL0 = " << +feiPicParams->MultiPredL0 << std::endl;
3573     oss << "MultiPredL1 = " << +feiPicParams->MultiPredL1 << std::endl;
3574     oss << "SubPelMode = " << +feiPicParams->SubPelMode << std::endl;
3575     oss << "AdaptiveSearch = " << +feiPicParams->AdaptiveSearch << std::endl;
3576     oss << "MVPredictorInput = " << +feiPicParams->MVPredictorInput << std::endl;
3577     oss << "bPerBlockQP = " << +feiPicParams->bPerBlockQP << std::endl;
3578     oss << "bPerCTBInput = " << +feiPicParams->bPerCTBInput << std::endl;
3579     oss << "bColocatedCTBDistortion = " << +feiPicParams->bColocatedCTBDistortion << std::endl;
3580     oss << "bForceLCUSplit = " << +feiPicParams->bForceLCUSplit << std::endl;
3581     oss << "bEnableCU64Check = " << +feiPicParams->bEnableCU64Check << std::endl;
3582     oss << "bEnableCU64AmpCheck = " << +feiPicParams->bEnableCU64AmpCheck << std::endl;
3583     oss << "bCU64SkipCheckOnly = " << +feiPicParams->bCU64SkipCheckOnly << std::endl;
3584     oss << "RefWidth = " << +feiPicParams->RefWidth << std::endl;
3585     oss << "RefHeight = " << +feiPicParams->RefHeight << std::endl;
3586     oss << "SearchWindow = " << +feiPicParams->SearchWindow << std::endl;
3587     oss << "MaxNumIMESearchCenter = " << +feiPicParams->MaxNumIMESearchCenter << std::endl;
3588     oss << "NumConcurrentEncFramePartition = " << +feiPicParams->NumConcurrentEncFramePartition << std::endl;
3589 
3590     const char *fileName = m_debugInterface->CreateFileName(
3591         "_DDIEnc",
3592         CodechalDbgBufferType::bufFeiPicParams,
3593         CodechalDbgExtType::txt);
3594 
3595     std::ofstream ofs(fileName, std::ios::out);
3596     ofs << oss.str();
3597     ofs.close();
3598 
3599     if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump))
3600     {
3601         if (!m_debugInterface->m_ddiFileName.empty())
3602         {
3603             std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app);
3604             ofs << "PicNum"
3605                 << " = \"" << m_debugInterface->m_bufferDumpFrameNum << "\"" << std::endl;
3606             ofs << "FeiPicParamFile"
3607                 << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl;
3608             ofs.close();
3609         }
3610     }
3611 
3612     return MOS_STATUS_SUCCESS;
3613 }
3614 
DumpSliceParams(PCODEC_HEVC_ENCODE_SLICE_PARAMS sliceParams,PCODEC_HEVC_ENCODE_PICTURE_PARAMS picParams)3615 MOS_STATUS CodechalEncodeHevcBase::DumpSliceParams(
3616     PCODEC_HEVC_ENCODE_SLICE_PARAMS   sliceParams,
3617     PCODEC_HEVC_ENCODE_PICTURE_PARAMS picParams)
3618 {
3619     CODECHAL_DEBUG_FUNCTION_ENTER;
3620     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSlcParams))
3621     {
3622         return MOS_STATUS_SUCCESS;
3623     }
3624 
3625     CODECHAL_DEBUG_CHK_NULL(sliceParams);
3626 
3627     m_debugInterface->m_sliceId = sliceParams->slice_id;  // set here for constructing debug file name
3628 
3629     std::ostringstream oss;
3630     oss.setf(std::ios::showbase | std::ios::uppercase);
3631 
3632     oss << "# DDI Parameters:" << std::endl;
3633     oss << "slice_segment_address = " << +sliceParams->slice_segment_address << std::endl;
3634     oss << "NumLCUsInSlice = " << +sliceParams->NumLCUsInSlice << std::endl;
3635 
3636     // RefPicList (2 x CODEC_MAX_NUM_REF_FRAME_HEVC)
3637     for (uint8_t i = 0; i < 2; ++i)
3638     {
3639         for (uint8_t j = 0; j < CODEC_MAX_NUM_REF_FRAME_HEVC; ++j)
3640         {
3641             oss << "RefPicList[" << +i << "][" << +j << "] = " << +sliceParams->RefPicList[i][j].PicEntry << std::endl;
3642         }
3643     }
3644 
3645     oss << "num_ref_idx_l0_active_minus1 = " << +sliceParams->num_ref_idx_l0_active_minus1 << std::endl;
3646     oss << "num_ref_idx_l1_active_minus1 = " << +sliceParams->num_ref_idx_l1_active_minus1 << std::endl;
3647     oss << "bLastSliceOfPic = " << +sliceParams->bLastSliceOfPic << std::endl;
3648     oss << "dependent_slice_segment_flag = " << +sliceParams->dependent_slice_segment_flag << std::endl;
3649     oss << "slice_temporal_mvp_enable_flag = " << +sliceParams->slice_temporal_mvp_enable_flag << std::endl;
3650     oss << "slice_type = " << +sliceParams->slice_type << std::endl;
3651     oss << "slice_sao_luma_flag = " << +sliceParams->slice_sao_luma_flag << std::endl;
3652     oss << "slice_sao_chroma_flag = " << +sliceParams->slice_sao_chroma_flag << std::endl;
3653     oss << "mvd_l1_zero_flag = " << +sliceParams->mvd_l1_zero_flag << std::endl;
3654     oss << "cabac_init_flag = " << +sliceParams->cabac_init_flag << std::endl;
3655     oss << "slice_deblocking_filter_disable_flag = " << +sliceParams->slice_deblocking_filter_disable_flag << std::endl;
3656     oss << "collocated_from_l0_flag = " << +sliceParams->collocated_from_l0_flag << std::endl;
3657     oss << "slice_qp_delta = " << +sliceParams->slice_qp_delta << std::endl;
3658     oss << "slice_cb_qp_offset = " << +sliceParams->slice_cb_qp_offset << std::endl;
3659     oss << "slice_cr_qp_offset = " << +sliceParams->slice_cr_qp_offset << std::endl;
3660     oss << "beta_offset_div2 = " << +sliceParams->beta_offset_div2 << std::endl;
3661     oss << "tc_offset_div2 = " << +sliceParams->tc_offset_div2 << std::endl;
3662     oss << "luma_log2_weight_denom = " << +sliceParams->luma_log2_weight_denom << std::endl;
3663     oss << "delta_chroma_log2_weight_denom = " << +sliceParams->delta_chroma_log2_weight_denom << std::endl;
3664 
3665     for (uint8_t i = 0; i < 2; ++i)
3666     {
3667         for (uint8_t j = 0; j < CODEC_MAX_NUM_REF_FRAME_HEVC; ++j)
3668         {
3669             oss << "luma_offset[" << +i << "][" << +j << "] = " << +sliceParams->luma_offset[i][j] << std::endl;
3670 
3671             oss << "delta_luma_weight[" << +i << "][" << +j << "] = " << +sliceParams->delta_luma_weight[i][j] << std::endl;
3672         }
3673     }
3674 
3675     for (uint8_t i = 0; i < 2; ++i)
3676     {
3677         for (uint8_t j = 0; j < CODEC_MAX_NUM_REF_FRAME_HEVC; ++j)
3678         {
3679             for (uint8_t k = 0; k < 2; ++k)
3680             {
3681                 oss << "chroma_offset[" << +i << "][" << +j << "][" << +k << "] = " << +sliceParams->chroma_offset[i][j][k] << std::endl;
3682                 oss << "delta_chroma_weight[" << +i << "][" << +j << "][" << +k << "] = " << +sliceParams->delta_chroma_weight[i][j][k] << std::endl;
3683             }
3684         }
3685     }
3686 
3687     oss << "PredWeightTableBitOffset = " << +sliceParams->PredWeightTableBitOffset << std::endl;
3688     oss << "PredWeightTableBitLength = " << +sliceParams->PredWeightTableBitLength << std::endl;
3689     oss << "MaxNumMergeCand = " << +sliceParams->MaxNumMergeCand << std::endl;
3690     oss << "slice_id = " << +sliceParams->slice_id << std::endl;
3691     oss << "SliceHeaderByteOffset = " << +sliceParams->SliceHeaderByteOffset << std::endl;
3692     oss << "BitLengthSliceHeaderStartingPortion = " << +sliceParams->BitLengthSliceHeaderStartingPortion << std::endl;
3693     oss << "SliceSAOFlagBitOffset = " << +sliceParams->SliceSAOFlagBitOffset << std::endl;
3694 
3695     const char *fileName = m_debugInterface->CreateFileName(
3696         "_DDIEnc",
3697         CodechalDbgBufferType::bufSlcParams,
3698         CodechalDbgExtType::txt);
3699 
3700     std::ofstream ofs(fileName, std::ios::out);
3701     ofs << oss.str();
3702     ofs.close();
3703 
3704     if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump))
3705     {
3706         if (!m_debugInterface->m_ddiFileName.empty())
3707         {
3708             std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app);
3709             ofs << "SlcParamFile"
3710                 << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl;
3711             ofs.close();
3712         }
3713     }
3714 
3715     return MOS_STATUS_SUCCESS;
3716 }
3717 
DumpMbEncPakOutput(PCODEC_REF_LIST currRefList,CodechalDebugInterface * debugInterface)3718 MOS_STATUS CodechalEncodeHevcBase::DumpMbEncPakOutput(PCODEC_REF_LIST currRefList, CodechalDebugInterface* debugInterface)
3719 {
3720     CODECHAL_ENCODE_FUNCTION_ENTER;
3721     CODECHAL_ENCODE_CHK_NULL_RETURN(currRefList);
3722     CODECHAL_ENCODE_CHK_NULL_RETURN(debugInterface);
3723 
3724     CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
3725         &currRefList->resRefMbCodeBuffer,
3726         CodechalDbgAttr::attrOutput,
3727         "PakObj",
3728         m_mvOffset,
3729         0,
3730         CODECHAL_MEDIA_STATE_ENC_NORMAL));
3731 
3732     CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
3733         &currRefList->resRefMbCodeBuffer,
3734         CodechalDbgAttr::attrOutput,
3735         "CuRecord",
3736         m_mbCodeSize - m_mvOffset,
3737         m_mvOffset,
3738         CODECHAL_MEDIA_STATE_ENC_NORMAL));
3739 
3740     return MOS_STATUS_SUCCESS;
3741 }
3742 
DumpFrameStatsBuffer(CodechalDebugInterface * debugInterface)3743 MOS_STATUS CodechalEncodeHevcBase::DumpFrameStatsBuffer(CodechalDebugInterface* debugInterface)
3744 {
3745     CODECHAL_ENCODE_FUNCTION_ENTER;
3746     CODECHAL_ENCODE_CHK_NULL_RETURN(debugInterface);
3747 
3748     CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
3749         &m_resFrameStatStreamOutBuffer,
3750         CodechalDbgAttr::attrFrameState,
3751         "FrameStatus",
3752         m_sizeOfHcpPakFrameStats,
3753         0,
3754         CODECHAL_NUM_MEDIA_STATES));
3755 
3756     return MOS_STATUS_SUCCESS;
3757 }
3758 #endif
3759