1 /*
2 * Copyright (c) 2016-2017, 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.cpp
24 //! \brief    Defines base class for HEVC dual-pipe encoder.
25 //!
26 
27 #include "codechal_encode_hevc.h"
28 #include "codechal_mmc_encode_hevc.h"
29 
GetStartCodeOffset(uint8_t * addr,uint32_t size)30 uint32_t CodechalEncHevcState::GetStartCodeOffset(uint8_t* addr, uint32_t size)
31 {
32     CODECHAL_ENCODE_FUNCTION_ENTER;
33 
34     uint32_t count = 0;
35 
36     if (addr)
37     {
38         // count # 0 bytes before end of start code to determine header offset
39         // (ie. 00 00 00 00 01 = 4)
40         while (count < size && *addr != 0x01)
41         {
42             // Damage control if start code is non-existent or malformed
43             // so header will still be a reasonable size
44             if (*addr != 0)
45                 break;
46 
47             count++;
48             addr++;
49         }
50     }
51 
52     return count + 1; // +1 to account for 01 byte
53 }
54 
GetPicHdrSize()55 uint32_t CodechalEncHevcState::GetPicHdrSize()
56 {
57     CODECHAL_ENCODE_FUNCTION_ENTER;
58 
59     uint32_t firstHdrSz = 0;
60     for(auto i = 0 ; i < HEVC_MAX_NAL_UNIT_TYPE ; i++)
61     {
62         if (m_nalUnitParams[i]->uiSize != 0)
63         {
64             firstHdrSz = m_nalUnitParams[i]->uiSize;
65             break;
66         }
67     }
68 
69     uint8_t* hdrPtr = m_bsBuffer.pBase;
70     // hdr offset = # 0's + 01 byte (start code) + offset over temporal ID and NAL type byte
71     uint32_t hdrBegin = GetStartCodeOffset(hdrPtr, firstHdrSz) + HEVC_START_CODE_NAL_OFFSET;
72 
73     uint32_t accum = 0, numEmuBytes = 0;
74     for(auto i = 0 ; i < HEVC_MAX_NAL_UNIT_TYPE ; i++)
75     {
76         if (m_nalUnitParams[i]->uiSize == 0)
77             continue;
78         uint32_t origSize = m_nalUnitParams[i]->uiSize;
79 
80         if (m_hevcPicParams->bEmulationByteInsertion)
81         {
82             hdrPtr = m_bsBuffer.pBase + accum;
83             uint32_t hdrOffset = GetStartCodeOffset(hdrPtr, origSize);
84             hdrPtr += hdrOffset;
85 
86             uint32_t zeroCount = 0;
87             for (uint32_t j = 0 ; j < origSize - hdrOffset ; j++)
88             {
89                 // Check if Emulation Prevention Byte needed for hex 00 00 00/00 00 01/00 00 02/00 00 03
90                 if (zeroCount == 2 && !(*hdrPtr & 0xFC))
91                 {
92                     zeroCount = 0;
93                     numEmuBytes++;   //increment by prevention byte
94                 }
95 
96                 if (*hdrPtr == 0x00)
97                 {
98                     zeroCount++;
99                 }
100                 else
101                 {
102                     zeroCount = 0;
103                 }
104 
105                 *hdrPtr++;
106             }
107         }
108 
109         accum += origSize;
110     }
111 
112     // Add emulation bytes found
113     accum += numEmuBytes;
114 
115     // Make sure that header size is valid or cap to provided hdr size
116     hdrBegin = MOS_MIN(hdrBegin, accum);
117 
118     // Hdr size is in # bits
119     return (accum - hdrBegin) * 8;
120 }
121 
ValidateRefFrameData(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)122 MOS_STATUS CodechalEncHevcState::ValidateRefFrameData(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)
123 {
124     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
125 
126     CODECHAL_ENCODE_CHK_NULL_RETURN(slcParams);
127 
128     uint8_t maxNumRef0 = 0;
129     uint8_t maxNumRef1 = 0;
130 
131     GetMaxRefFrames(maxNumRef0, maxNumRef1);
132 
133     if (slcParams->num_ref_idx_l0_active_minus1 > maxNumRef0 - 1)
134     {
135         CODECHAL_ENCODE_ASSERT(false);
136         slcParams->num_ref_idx_l0_active_minus1 = maxNumRef0 - 1;
137     }
138 
139     if (slcParams->num_ref_idx_l1_active_minus1 > maxNumRef1 - 1)
140     {
141         CODECHAL_ENCODE_ASSERT(false);
142         slcParams->num_ref_idx_l1_active_minus1 = maxNumRef1 - 1;
143     }
144 
145     return eStatus;
146 }
147 
SetSequenceStructs()148 MOS_STATUS CodechalEncHevcState::SetSequenceStructs()
149 {
150     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
151 
152     CODECHAL_ENCODE_FUNCTION_ENTER;
153 
154     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeHevcBase::SetSequenceStructs());
155 
156     m_cqpEnabled = (m_hevcSeqParams->RateControlMethod == RATECONTROL_CQP);
157 
158     if (m_hevcSeqParams->ParallelBRC == false)
159     {
160         m_brcBuffers.uiCurrBrcPakStasIdxForRead = m_brcBuffers.uiCurrBrcPakStasIdxForWrite = 0;
161     }
162 
163     // check LCU size
164     if (m_2xMeSupported &&
165         m_hevcSeqParams->log2_max_coding_block_size_minus3 == 3)
166     {
167         // LCU64 support
168         m_isMaxLcu64       = true;
169         m_2xScalingEnabled = true;
170     }
171     else
172     {
173         if (m_hevcSeqParams->log2_max_coding_block_size_minus3 != 2)
174         {
175             CODECHAL_ENCODE_ASSERTMESSAGE("Invalid LCU.");
176             eStatus = MOS_STATUS_INVALID_PARAMETER;
177             return eStatus;
178         }
179 
180         m_isMaxLcu64       = false;
181         m_2xScalingEnabled = false;
182     }
183 
184     // allocate resources only needed in LCU64 kernel
185     if (m_firstFrame && m_isMaxLcu64)
186     {
187         CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateEncResourcesLCU64());
188     }
189 
190     if (m_hevcSeqParams->FrameRate.Denominator == 0)
191     {
192         eStatus = MOS_STATUS_INVALID_PARAMETER;
193         CODECHAL_ENCODE_ASSERTMESSAGE("FrameRate Denominator can not be zero.");
194         return eStatus;
195     }
196     uint8_t framerate = m_hevcSeqParams->FrameRate.Numerator / m_hevcSeqParams->FrameRate.Denominator;
197 
198     m_slidingWindowSize = MOS_MIN(framerate, 60);
199 
200     return eStatus;
201 }
202 
SetPictureStructs()203 MOS_STATUS CodechalEncHevcState::SetPictureStructs()
204 {
205     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
206 
207     CODECHAL_ENCODE_FUNCTION_ENTER;
208 
209     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeHevcBase::SetPictureStructs());
210 
211     // do not support interlaced coding now
212     if (CodecHal_PictureIsField(m_currOriginalPic))
213     {
214         eStatus = MOS_STATUS_INVALID_PARAMETER;
215         return eStatus;
216     }
217 
218         // Set min/max QP values based on frame type if atleast one of them is non-zero
219     if (m_hevcPicParams->BRCMinQp || m_hevcPicParams->BRCMaxQp)
220     {
221         m_minMaxQpControlEnabled = true;
222         if (m_hevcPicParams->CodingType == I_TYPE)
223         {
224             m_maxQpForI = MOS_MIN(MOS_MAX(m_hevcPicParams->BRCMaxQp, 1), 51);           // Clamp to the max QP to [1, 51] . Zero is not used by our Kernel.
225             m_minQpForI = MOS_MIN(MOS_MAX(m_hevcPicParams->BRCMinQp, 1), m_maxQpForI);  // Clamp the min QP to [1, maxQP] to make sure minQP <= maxQP
226             if (!m_minMaxQpControlForP)
227             {
228                 m_minQpForP = m_minQpForI;
229                 m_maxQpForP = m_maxQpForI;
230             }
231             if (!m_minMaxQpControlForB)
232             {
233                 m_minQpForB = m_minQpForI;
234                 m_maxQpForB = m_maxQpForI;
235             }
236         }
237         else if (m_hevcPicParams->CodingType == P_TYPE)
238         {
239             m_minMaxQpControlForP = true;
240             m_maxQpForP           = MOS_MIN(MOS_MAX(m_hevcPicParams->BRCMaxQp, 1), 51);           // Clamp to the max QP to [1, 51]. Zero is not used by our Kernel.
241             m_minQpForP           = MOS_MIN(MOS_MAX(m_hevcPicParams->BRCMinQp, 1), m_maxQpForP);  // Clamp the min QP to [1, maxQP] to make sure minQP <= maxQP
242             if (!m_minMaxQpControlForB)
243             {
244                 m_minQpForB = m_minQpForP;
245                 m_maxQpForB = m_maxQpForP;
246             }
247         }
248         else if (m_hevcPicParams->CodingType == B_TYPE)
249         {
250             m_minMaxQpControlForB = true;
251             m_maxQpForB           = MOS_MIN(MOS_MAX(m_hevcPicParams->BRCMaxQp, 1), 51);           // Clamp to the max QP to [1, 51]. Zero is not used by our Kernel.
252             m_minQpForB           = MOS_MIN(MOS_MAX(m_hevcPicParams->BRCMinQp, 1), m_maxQpForB);  // Clamp the min QP to [1, maxQP] to make sure minQP <= maxQP
253         }
254     }
255 
256     // CQP with Fast Surveillance [Distortion Surface needs to be allocated]
257     if (m_brcEnabled || m_hevcSeqParams->bVideoSurveillance || m_cqpEnabled)
258     {
259         m_brcDistortion = (m_pictureCodingType == I_TYPE) ? &m_brcBuffers.sBrcIntraDistortionBuffer : &m_brcBuffers.sMeBrcDistortionBuffer;
260     }
261 
262     if (m_brcEnabled)
263     {
264         // For ICQ mode or when min/max QP used, ignore BRCPrecision sent by the app and set the number of passes internally
265         if ((m_hevcSeqParams->RateControlMethod == RATECONTROL_ICQ) || (m_minMaxQpControlEnabled))
266         {
267             m_numPasses = 0;  // no IPCM for HEVC
268         }
269         else
270         {
271             m_numPasses = (uint8_t)(m_mfxInterface->GetBrcNumPakPasses() - 1);  // 1 original plus extra to handle BRC
272         }
273     }
274     else
275     {
276         m_numPasses = 0;  // no IPCM for HEVC
277     }
278 
279     //add for FEI multiple Pass Pak
280     if (CodecHalIsFeiEncode(m_codecFunction))
281     {
282         CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcFeiPicParams);
283         if (m_hevcFeiPicParams->dwMaxFrameSize != 0)
284         {
285             m_numPasses = (uint8_t)m_hevcFeiPicParams->dwNumPasses;
286         }
287     }
288 
289     return eStatus;
290 }
291 
SetSliceStructs()292 MOS_STATUS CodechalEncHevcState::SetSliceStructs()
293 {
294     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
295 
296     CODECHAL_ENCODE_FUNCTION_ENTER;
297 
298     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeHevcBase::SetSliceStructs());
299 
300     return eStatus;
301 }
302 
ReadBrcPakStats(PMOS_COMMAND_BUFFER cmdBuffer)303 MOS_STATUS CodechalEncHevcState::ReadBrcPakStats(
304     PMOS_COMMAND_BUFFER cmdBuffer)
305 {
306     MOS_STATUS  eStatus = MOS_STATUS_SUCCESS;
307 
308     CODECHAL_ENCODE_FUNCTION_ENTER;
309 
310     uint32_t offset = (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize) +
311         m_encodeStatusBuf.dwNumPassesOffset +   // Num passes offset
312         sizeof(uint32_t)* 2;                               // pEncodeStatus is offset by 2 DWs in the resource
313 
314     EncodeReadBrcPakStatsParams   readBrcPakStatsParams;
315     readBrcPakStatsParams.pHwInterface               = m_hwInterface;
316     readBrcPakStatsParams.presBrcPakStatisticBuffer  = &m_brcBuffers.resBrcPakStatisticBuffer[m_brcBuffers.uiCurrBrcPakStasIdxForWrite];
317     readBrcPakStatsParams.presStatusBuffer           = &m_encodeStatusBuf.resStatusBuffer;
318     readBrcPakStatsParams.dwStatusBufNumPassesOffset = offset;
319     readBrcPakStatsParams.ucPass                     = (uint8_t)GetCurrentPass();
320     readBrcPakStatsParams.VideoContext               = m_videoContext;
321 
322     CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadBrcPakStatistics(
323         cmdBuffer,
324         &readBrcPakStatsParams));
325 
326     return eStatus;
327 }
328 
AddHcpPipeModeSelectCmd(MOS_COMMAND_BUFFER * cmdBuffer)329 MOS_STATUS CodechalEncHevcState::AddHcpPipeModeSelectCmd(MOS_COMMAND_BUFFER* cmdBuffer)
330 {
331     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
332 
333     MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams;
334     SetHcpPipeModeSelectParams(pipeModeSelectParams);
335     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPipeModeSelectCmd(cmdBuffer, &pipeModeSelectParams));
336 
337     return eStatus;
338 }
339 
AddHcpSurfaceStateCmds(MOS_COMMAND_BUFFER * cmdBuffer)340 MOS_STATUS CodechalEncHevcState::AddHcpSurfaceStateCmds(MOS_COMMAND_BUFFER* cmdBuffer)
341 {
342     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
343 
344     MHW_VDBOX_SURFACE_PARAMS srcSurfaceParams;
345     SetHcpSrcSurfaceParams(srcSurfaceParams);
346     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpSurfaceCmd(cmdBuffer, &srcSurfaceParams));
347 
348     MHW_VDBOX_SURFACE_PARAMS reconSurfaceParams;
349     SetHcpReconSurfaceParams(reconSurfaceParams);
350     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpSurfaceCmd(cmdBuffer, &reconSurfaceParams));
351 
352     return eStatus;
353 }
354 
AddHcpPictureStateCmd(MOS_COMMAND_BUFFER * cmdBuffer)355 MOS_STATUS CodechalEncHevcState::AddHcpPictureStateCmd(MOS_COMMAND_BUFFER* cmdBuffer)
356 {
357     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
358 
359     MHW_VDBOX_HEVC_PIC_STATE picStateParams;
360     SetHcpPicStateParams(picStateParams);
361 
362     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPicStateCmd(cmdBuffer, &picStateParams));
363 
364     return eStatus;
365 }
366 
ExecutePictureLevel()367 MOS_STATUS CodechalEncHevcState::ExecutePictureLevel()
368 {
369     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
370 
371     CODECHAL_ENCODE_FUNCTION_ENTER;
372 
373     PerfTagSetting perfTag;
374     CODECHAL_ENCODE_SET_PERFTAG_INFO(perfTag, CODECHAL_ENCODE_PERFTAG_CALL_PAK_ENGINE);
375 
376     CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifyCommandBufferSize());
377 
378     if (!m_singleTaskPhaseSupportedInPak)
379     {
380         // Command buffer or patch list size are too small and so we cannot submit multiple pass of PAKs together
381         m_firstTaskInPhase = true;
382         m_lastTaskInPhase  = true;
383     }
384 
385     if (m_vdboxIndex > m_mfxInterface->GetMaxVdboxIndex())
386     {
387         CODECHAL_ENCODE_ASSERTMESSAGE("ERROR - vdbox index exceed the maximum");
388         eStatus = MOS_STATUS_INVALID_PARAMETER;
389         return eStatus;
390     }
391 
392     MOS_COMMAND_BUFFER cmdBuffer;
393     CODECHAL_ENCODE_CHK_STATUS_RETURN(GetCommandBuffer(&cmdBuffer));
394 
395     if ((!m_singleTaskPhaseSupported) || m_firstTaskInPhase)
396     {
397         // Send command buffer header at the beginning (OS dependent)
398         // frame tracking tag is only added in the last command buffer header
399         bool requestFrameTracking = m_singleTaskPhaseSupported ?
400             m_firstTaskInPhase :
401             m_lastTaskInPhase;
402 
403         // When brc + 2 pass sao is enabled need to disable frame tracking for first cmd buffer
404         if (m_brcEnabled && m_hevcSeqParams->SAO_enabled_flag)
405         {
406             requestFrameTracking = false;
407         }
408 
409         CODECHAL_ENCODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, requestFrameTracking));
410     }
411 
412     // Enable frame tracking for the last cmd buffer when brc + 2 pass sao is on
413     if (m_brcEnabled && m_hevcSeqParams->SAO_enabled_flag && m_currPass == m_uc2NdSaoPass)
414     {
415         CODECHAL_ENCODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, true));
416     }
417 
418     if (m_brcEnabled &&
419         !IsFirstPass() &&
420         m_currPass != m_uc2NdSaoPass)  // Only the regular BRC passes have the conditional batch buffer end
421     {
422         // Insert conditional batch buffer end
423         MHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS miConditionalBatchBufferEndParams;
424         MOS_ZeroMemory(
425             &miConditionalBatchBufferEndParams,
426             sizeof(MHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS));
427         uint32_t baseOffset = (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize) +
428                 sizeof(uint32_t) * 2;  // pEncodeStatus is offset by 2 DWs in the resource       ;
429 
430         CODECHAL_ENCODE_ASSERT((m_encodeStatusBuf.dwImageStatusMaskOffset & 7) == 0); // Make sure uint64_t aligned
431         CODECHAL_ENCODE_ASSERT((m_encodeStatusBuf.dwImageStatusMaskOffset + sizeof(uint32_t)) == m_encodeStatusBuf.dwImageStatusCtrlOffset);
432 
433         miConditionalBatchBufferEndParams.presSemaphoreBuffer = &m_encodeStatusBuf.resStatusBuffer;
434         miConditionalBatchBufferEndParams.dwOffset = baseOffset + m_encodeStatusBuf.dwImageStatusMaskOffset;
435 
436         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiConditionalBatchBufferEndCmd(
437             &cmdBuffer,
438             &miConditionalBatchBufferEndParams));
439 
440         auto mmioRegisters = m_hcpInterface->GetMmioRegisters(m_vdboxIndex);
441         MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
442         MHW_MI_COPY_MEM_MEM_PARAMS miCpyMemMemParams;
443         // Write back the HCP image control register for RC6 may clean it out
444         MHW_MI_LOAD_REGISTER_MEM_PARAMS miLoadRegMemParams;
445         MOS_ZeroMemory(&miLoadRegMemParams, sizeof(miLoadRegMemParams));
446         miLoadRegMemParams.presStoreBuffer = &m_encodeStatusBuf.resStatusBuffer;
447         miLoadRegMemParams.dwOffset = baseOffset + m_encodeStatusBuf.dwImageStatusCtrlOffset;
448         miLoadRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusCtrlRegOffset;
449         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(&cmdBuffer, &miLoadRegMemParams));
450 
451         MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
452         miStoreRegMemParams.presStoreBuffer = &m_brcBuffers.resBrcPakStatisticBuffer[m_brcBuffers.uiCurrBrcPakStasIdxForWrite];
453         miStoreRegMemParams.dwOffset = CODECHAL_OFFSETOF(CODECHAL_ENCODE_HEVC_PAK_STATS_BUFFER, HCP_IMAGE_STATUS_CONTROL_FOR_LAST_PASS);
454         miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusCtrlRegOffset;
455         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(&cmdBuffer, &miStoreRegMemParams));
456 
457         MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
458         miStoreRegMemParams.presStoreBuffer =  &m_encodeStatusBuf.resStatusBuffer;
459         miStoreRegMemParams.dwOffset = baseOffset + m_encodeStatusBuf.dwImageStatusCtrlOfLastBRCPassOffset;
460         miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusCtrlRegOffset;
461         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(&cmdBuffer, &miStoreRegMemParams));
462     }
463 
464     if (IsFirstPass() && m_osInterface->bTagResourceSync)
465     {
466         // This is a short term solution to solve the sync tag issue: the sync tag write for PAK is inserted at the end of 2nd pass PAK BB
467         // which may be skipped in multi-pass PAK enabled case. The idea here is to insert the previous frame's tag at the beginning
468         // of the BB and keep the current frame's tag at the end of the BB. There will be a delay for tag update but it should be fine
469         // as long as Dec/VP/Enc won't depend on this PAK so soon.
470 
471         MOS_RESOURCE globalGpuContextSyncTagBuffer;
472         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetGpuStatusBufferResource(
473             m_osInterface,
474             &globalGpuContextSyncTagBuffer));
475 
476         MHW_MI_STORE_DATA_PARAMS params;
477         params.pOsResource = &globalGpuContextSyncTagBuffer;
478         params.dwResourceOffset = m_osInterface->pfnGetGpuStatusTagOffset(m_osInterface, m_osInterface->CurrentGpuContextOrdinal);
479         uint32_t value = m_osInterface->pfnGetGpuStatusTag(m_osInterface, m_osInterface->CurrentGpuContextOrdinal);
480         params.dwValue = (value > 0) ? (value - 1) : 0;
481         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(&cmdBuffer, &params));
482     }
483 
484     CODECHAL_ENCODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES));
485 
486     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPipeModeSelectCmd(&cmdBuffer));
487 
488     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpSurfaceStateCmds(&cmdBuffer));
489 
490     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPipeBufAddrCmd(&cmdBuffer));
491 
492     MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams;
493     SetHcpIndObjBaseAddrParams(indObjBaseAddrParams);
494     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpIndObjBaseAddrCmd(&cmdBuffer, &indObjBaseAddrParams));
495 
496     MHW_VDBOX_QM_PARAMS fqmParams, qmParams;
497     SetHcpQmStateParams(fqmParams, qmParams);
498     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpFqmStateCmd(&cmdBuffer, &fqmParams));
499     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpQmStateCmd(&cmdBuffer, &qmParams));
500 
501     if (m_brcEnabled)
502     {
503         if (m_hevcSeqParams->SAO_enabled_flag && m_currPass == m_uc2NdSaoPass)
504         {
505             CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPictureStateCmd(&cmdBuffer));
506         }
507         else
508         {
509             uint32_t picStateCmdOffset;
510             picStateCmdOffset = GetCurrentPass();
511 
512             MHW_BATCH_BUFFER batchBuffer;
513             MOS_ZeroMemory(&batchBuffer, sizeof(batchBuffer));
514             batchBuffer.OsResource = m_brcBuffers.resBrcImageStatesWriteBuffer[m_currRecycledBufIdx];
515             batchBuffer.dwOffset = picStateCmdOffset * (m_brcBuffers.dwBrcHcpPicStateSize / CODECHAL_ENCODE_BRC_MAXIMUM_NUM_PASSES);
516             batchBuffer.bSecondLevel = true;
517 
518             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(
519                 &cmdBuffer,
520                 &batchBuffer));
521         }
522     }
523     else
524     {
525         CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPictureStateCmd(&cmdBuffer));
526     }
527 
528     // Send HEVC_VP9_RDOQ_STATE command
529     if (m_hevcRdoqEnabled)
530     {
531         MHW_VDBOX_HEVC_PIC_STATE picStateParams;
532         SetHcpPicStateParams(picStateParams);
533 
534         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpHevcVp9RdoqStateCmd(&cmdBuffer, &picStateParams));
535     }
536 
537     CODECHAL_ENCODE_CHK_STATUS_RETURN(ReturnCommandBuffer(&cmdBuffer));
538 
539     return eStatus;
540 }
541 
AddHcpWeightOffsetStateCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PCODEC_HEVC_ENCODE_SLICE_PARAMS hevcSlcParams)542 MOS_STATUS CodechalEncHevcState::AddHcpWeightOffsetStateCmd(
543     PMOS_COMMAND_BUFFER             cmdBuffer,
544     PMHW_BATCH_BUFFER               batchBuffer,
545     PCODEC_HEVC_ENCODE_SLICE_PARAMS hevcSlcParams)
546 {
547     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
548 
549     CODECHAL_ENCODE_FUNCTION_ENTER;
550 
551     CODECHAL_ENCODE_CHK_NULL_RETURN(hevcSlcParams);
552 
553     if (cmdBuffer == nullptr && batchBuffer == nullptr)
554     {
555         CODECHAL_ENCODE_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
556         return MOS_STATUS_NULL_POINTER;
557     }
558 
559     MHW_VDBOX_HEVC_WEIGHTOFFSET_PARAMS hcpWeightOffsetParams;
560     MOS_ZeroMemory(&hcpWeightOffsetParams, sizeof(hcpWeightOffsetParams));
561 
562     for (auto k = 0; k < 2; k++) // k=0: LIST_0, k=1: LIST_1
563     {
564         // Luma, Chroma offset
565         for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
566         {
567             hcpWeightOffsetParams.LumaOffsets[k][i] = (int16_t)hevcSlcParams->luma_offset[k][i];
568             // Cb, Cr
569             for (auto j = 0; j < 2; j++)
570             {
571                 hcpWeightOffsetParams.ChromaOffsets[k][i][j] = (int16_t)hevcSlcParams->chroma_offset[k][i][j];
572             }
573         }
574 
575         // Luma Weight
576         CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(
577             &hcpWeightOffsetParams.LumaWeights[k],
578             sizeof(hcpWeightOffsetParams.LumaWeights[k]),
579             &hevcSlcParams->delta_luma_weight[k],
580             sizeof(hevcSlcParams->delta_luma_weight[k])));
581 
582         // Chroma Weight
583         CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(
584             &hcpWeightOffsetParams.ChromaWeights[k],
585             sizeof(hcpWeightOffsetParams.ChromaWeights[k]),
586             &hevcSlcParams->delta_chroma_weight[k],
587             sizeof(hevcSlcParams->delta_chroma_weight[k])));
588     }
589 
590     if (hevcSlcParams->slice_type == CODECHAL_ENCODE_HEVC_P_SLICE || hevcSlcParams->slice_type == CODECHAL_ENCODE_HEVC_B_SLICE)
591     {
592         hcpWeightOffsetParams.ucList = LIST_0;
593         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpWeightOffsetStateCmd(cmdBuffer, batchBuffer, &hcpWeightOffsetParams));
594     }
595 
596     if (hevcSlcParams->slice_type == CODECHAL_ENCODE_HEVC_B_SLICE)
597     {
598         hcpWeightOffsetParams.ucList = LIST_1;
599         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpWeightOffsetStateCmd(cmdBuffer, batchBuffer, &hcpWeightOffsetParams));
600     }
601 
602     return eStatus;
603 }
604 
605 //------------------------------------------------------------------------------------
606 // Build slices with header insertion
607 //------------------------------------------------------------------------------------
SendHwSliceEncodeCommand(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_HEVC_SLICE_STATE params)608 MOS_STATUS CodechalEncHevcState::SendHwSliceEncodeCommand(
609     PMOS_COMMAND_BUFFER             cmdBuffer,
610     PMHW_VDBOX_HEVC_SLICE_STATE     params)
611 {
612     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
613 
614     CODECHAL_ENCODE_FUNCTION_ENTER;
615 
616     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
617     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pHevcPicIdx);
618     CODECHAL_ENCODE_CHK_NULL_RETURN(params->presDataBuffer);
619     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeHevcSeqParams);
620     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeHevcPicParams);
621     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeHevcSliceParams);
622     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
623     CODECHAL_ENCODE_CHK_NULL_RETURN(params->ppNalUnitParams);
624 
625     PMHW_BATCH_BUFFER batchBufferInUse = nullptr;
626     PMOS_COMMAND_BUFFER cmdBufferInUse = nullptr;
627 
628     if (params->bSingleTaskPhaseSupported)
629     {
630         CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBatchBufferForPakSlices);
631         batchBufferInUse = params->pBatchBufferForPakSlices;
632     }
633     else
634     {
635         cmdBufferInUse = cmdBuffer;
636     }
637 
638     // add HCP_REF_IDX command
639     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpRefIdxCmd(cmdBufferInUse, batchBufferInUse, params));
640 
641     if (params->bWeightedPredInUse)
642     {
643         //add weghtoffset command
644         CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpWeightOffsetStateCmd(cmdBufferInUse, batchBufferInUse, m_hevcSliceParams));
645     }
646 
647     // add HEVC Slice state commands
648     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpSliceStateCmd(cmdBufferInUse, params));
649 
650     // add HCP_PAK_INSERT_OBJECTS command
651     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPakInsertNALUs(cmdBufferInUse, batchBufferInUse, params));
652 
653     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPakInsertSliceHeader(cmdBufferInUse, batchBufferInUse, params));
654 
655     if (params->bSingleTaskPhaseSupported && batchBufferInUse)
656     {
657         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(nullptr, batchBufferInUse));
658 
659         MHW_BATCH_BUFFER secondLevelBatchBuffer;
660         MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(MHW_BATCH_BUFFER));
661         secondLevelBatchBuffer.OsResource = batchBufferInUse->OsResource;
662         secondLevelBatchBuffer.dwOffset = params->dwBatchBufferForPakSlicesStartOffset;
663         secondLevelBatchBuffer.bSecondLevel = true;
664         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(cmdBuffer, &secondLevelBatchBuffer));
665     }
666 
667     // Insert Batch Buffer Start command to send HCP_PAK_OBJ data for LCUs in this slice
668     MHW_BATCH_BUFFER secondLevelBatchBuffer;
669     MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(MHW_BATCH_BUFFER));
670     secondLevelBatchBuffer.OsResource = *params->presDataBuffer;
671     secondLevelBatchBuffer.dwOffset = params->dwDataBufferOffset;
672     secondLevelBatchBuffer.bSecondLevel = true;
673     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(cmdBuffer, &secondLevelBatchBuffer));
674 
675     return eStatus;
676 }
677 
ExecuteSliceLevel()678 MOS_STATUS CodechalEncHevcState::ExecuteSliceLevel()
679 {
680     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
681 
682     CODECHAL_ENCODE_FUNCTION_ENTER;
683 
684     CODECHAL_ENCODE_CHK_NULL_RETURN(m_slcData);
685     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetBatchBufferForPakSlices());
686 
687     MOS_COMMAND_BUFFER cmdBuffer;
688     CODECHAL_ENCODE_CHK_STATUS_RETURN(GetCommandBuffer(&cmdBuffer));
689 
690     SetHcpSliceStateCommonParams(*m_sliceStateParams);
691 
692     PCODEC_ENCODER_SLCDATA slcData = m_slcData;
693     for (uint32_t startLCU = 0, SlcCount = 0; SlcCount < m_numSlices; SlcCount++)
694     {
695         if (m_currPass == 0)
696         {
697             slcData[SlcCount].CmdOffset = startLCU * (m_hcpInterface->GetHcpPakObjSize()) * sizeof(uint32_t);
698         }
699 
700         SetHcpSliceStateParams(*m_sliceStateParams, slcData, SlcCount);
701 
702         CODECHAL_ENCODE_CHK_STATUS_RETURN(SendHwSliceEncodeCommand(&cmdBuffer, m_sliceStateParams));
703 
704         startLCU += m_hevcSliceParams[SlcCount].NumLCUsInSlice;
705 
706         m_batchBufferForPakSlicesStartOffset =
707             (uint32_t)m_batchBufferForPakSlices[m_currPakSliceIdx].iCurrent;
708     }
709 
710     if (m_useBatchBufferForPakSlices)
711     {
712         CODECHAL_ENCODE_CHK_STATUS_RETURN(Mhw_UnlockBb(
713             m_osInterface,
714             &m_batchBufferForPakSlices[m_currPakSliceIdx],
715             m_lastTaskInPhase));
716     }
717 
718     // Insert end of sequence/stream if set
719     if (m_lastPicInStream || m_lastPicInSeq)
720     {
721         MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams;
722         MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams));
723         pakInsertObjectParams.bLastPicInSeq     = m_lastPicInSeq;
724         pakInsertObjectParams.bLastPicInStream  = m_lastPicInStream;
725         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPakInsertObject(&cmdBuffer, &pakInsertObjectParams));
726     }
727 
728     CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadHcpStatus(&cmdBuffer));
729 
730     // BRC PAK statistics different for each pass
731     if (m_brcEnabled)
732     {
733         CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadBrcPakStats(&cmdBuffer));
734     }
735 
736     if (!Mos_ResourceIsNull(&m_resFrameStatStreamOutBuffer))
737     {
738         CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadSseStatistics(&cmdBuffer));
739     }
740 
741     CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES));
742 
743     if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
744     {
745         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
746     }
747 
748     std::string pakPassName = "PAK_PASS" + std::to_string(static_cast<uint32_t>(m_currPass));
749     CODECHAL_DEBUG_TOOL(
750         CODECHAL_ENCODE_CHK_STATUS_RETURN( m_debugInterface->DumpCmdBuffer(
751             &cmdBuffer,
752             CODECHAL_NUM_MEDIA_STATES,
753             pakPassName.data()));)
754 
755     CODECHAL_ENCODE_CHK_STATUS_RETURN(ReturnCommandBuffer(&cmdBuffer));
756 
757     if ((!m_pakOnlyTest) &&  // In the PAK only test, no need to wait for ENC's completion
758         (m_currPass == 0) &&
759         !Mos_ResourceIsNull(&m_resSyncObjectRenderContextInUse))
760     {
761         MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
762         syncParams.GpuContext = m_videoContext;
763         syncParams.presSyncResource = &m_resSyncObjectRenderContextInUse;
764 
765         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
766     }
767 
768     bool renderingFlags = m_videoContextUsesNullHw;
769 
770     if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
771     {
772         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, renderingFlags));
773 
774         CODECHAL_DEBUG_TOOL(
775             if (m_mmcState)
776             {
777                 m_mmcState->UpdateUserFeatureKey(&m_reconSurface);
778             }
779         )
780 
781         if ((m_currPass == m_numPasses) &&
782             m_signalEnc &&
783             m_currRefSync &&
784             !Mos_ResourceIsNull(&m_currRefSync->resSyncObject))
785         {
786             // signal semaphore
787             MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
788             syncParams.GpuContext = m_videoContext;
789             syncParams.presSyncResource = &m_currRefSync->resSyncObject;
790 
791             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
792             m_currRefSync->uiSemaphoreObjCount++;
793             m_currRefSync->bInUsed = true;
794         }
795     }
796 
797     // Reset parameters for next PAK execution
798     if (m_currPass == m_numPasses)
799     {
800         if (!m_singleTaskPhaseSupported)
801         {
802             m_osInterface->pfnResetPerfBufferID(m_osInterface);
803         }
804 
805         m_currPakSliceIdx = (m_currPakSliceIdx + 1) % CODECHAL_HEVC_NUM_PAK_SLICE_BATCH_BUFFERS;
806 
807         if (m_hevcSeqParams->ParallelBRC)
808         {
809             m_brcBuffers.uiCurrBrcPakStasIdxForWrite =
810                 (m_brcBuffers.uiCurrBrcPakStasIdxForWrite + 1) % CODECHAL_ENCODE_RECYCLED_BUFFER_NUM;
811         }
812 
813         m_newPpsHeader = 0;
814         m_newSeqHeader = 0;
815         m_frameNum++;
816     }
817 
818     return eStatus;
819 }
820 
821 //------------------------------------------------------------------------------
822 //| Purpose:    Retrieves the HCP registers and stores them in the status report
823 //| Return:     N/A
824 //------------------------------------------------------------------------------
ReadHcpStatus(PMOS_COMMAND_BUFFER cmdBuffer)825 MOS_STATUS CodechalEncHevcState::ReadHcpStatus(PMOS_COMMAND_BUFFER cmdBuffer)
826 {
827     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
828 
829     CODECHAL_ENCODE_FUNCTION_ENTER;
830 
831     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
832 
833     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeHevcBase::ReadHcpStatus(cmdBuffer));
834 
835     CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadImageStatus(cmdBuffer))
836 
837     return eStatus;
838 }
839 
CalculateROIRatio()840 uint8_t CodechalEncHevcState::CalculateROIRatio()
841 {
842     uint32_t roiSize = 0;
843     for (uint32_t i = 0; i < m_hevcPicParams->NumROI; ++i)
844     {
845         roiSize += (ENCODE_DP_HEVC_ROI_BLOCK_Width * (MOS_ABS(m_hevcPicParams->ROI[i].Top - m_hevcPicParams->ROI[i].Bottom) + 1 )) *
846                    (ENCODE_DP_HEVC_ROI_BLOCK_HEIGHT * (MOS_ABS(m_hevcPicParams->ROI[i].Right - m_hevcPicParams->ROI[i].Left) + 1));
847     }
848 
849     uint32_t roiRatio = 0;
850     if (roiSize)
851     {
852         uint32_t numMBs = m_picWidthInMb * m_picHeightInMb;
853         roiRatio = 2 * (numMBs * 256 / roiSize - 1);
854         roiRatio = MOS_MIN(51, roiRatio);
855     }
856 
857     return (uint8_t)roiRatio;
858 }
859 
ComputeTemporalDifference(const CODEC_PICTURE & refPic)860 int16_t CodechalEncHevcState::ComputeTemporalDifference(const CODEC_PICTURE& refPic)
861 {
862     int16_t diff_poc = 0;
863 
864     if (!CodecHal_PictureIsInvalid(refPic))
865     {
866         diff_poc = m_hevcPicParams->CurrPicOrderCnt - m_hevcPicParams->RefFramePOCList[refPic.FrameIdx];
867 
868         if(diff_poc < -128)
869         {
870             diff_poc = -128;
871         }
872         else if(diff_poc > 127)
873         {
874             diff_poc = 127;
875         }
876     }
877 
878     return diff_poc;
879 }
880 
WaitForRefFrameReady(uint8_t mbCodeIdx)881 MOS_STATUS CodechalEncHevcState::WaitForRefFrameReady(uint8_t mbCodeIdx)
882 {
883     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
884 
885     CODECHAL_ENCODE_FUNCTION_ENTER;
886 
887     if (!m_refSync[mbCodeIdx].bInUsed)
888     {
889         return eStatus;
890     }
891 
892     MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
893     syncParams.GpuContext = m_renderContext;
894     syncParams.presSyncResource = &m_refSync[mbCodeIdx].resSyncObject;
895     syncParams.uiSemaphoreCount = m_refSync[mbCodeIdx].uiSemaphoreObjCount;
896 
897     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
898     m_refSync[mbCodeIdx].uiSemaphoreObjCount = 0;
899     m_refSync[mbCodeIdx].bInUsed             = false;
900 
901     return eStatus;
902 }
903 
WaitForPak()904 MOS_STATUS CodechalEncHevcState::WaitForPak()
905 {
906     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
907 
908     CODECHAL_ENCODE_FUNCTION_ENTER;
909 
910     if (m_pictureCodingType == I_TYPE && !m_brcEnabled)
911     {
912         return eStatus;
913     }
914 
915     if (!m_firstFrame && m_brcEnabled && !m_hevcSeqParams->ParallelBRC)
916     {
917         // When there is no parallel BRC, we still need to wait for previous PAK
918         CODECHAL_ENCODE_CHK_STATUS_RETURN(WaitForRefFrameReady(m_lastMbCodeIndex));
919         return eStatus;
920     }
921 
922     // 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.
923     auto slcParams = m_hevcSliceParams;
924     for (uint32_t s = 0; s < m_numSlices; s++, slcParams++)
925     {
926         for (auto ll = 0; ll < 2; ll++)
927         {
928             uint32_t uiNumRef = (ll == 0) ? slcParams->num_ref_idx_l0_active_minus1 :
929                 slcParams->num_ref_idx_l1_active_minus1;
930 
931             for (uint32_t i = 0; i <= uiNumRef; i++)
932             {
933                 CODEC_PICTURE refPic = slcParams->RefPicList[ll][i];
934                 if (!CodecHal_PictureIsInvalid(refPic) &&
935                     !CodecHal_PictureIsInvalid(m_hevcPicParams->RefFrameList[refPic.FrameIdx]))
936                 {
937                     uint32_t idx       = m_hevcPicParams->RefFrameList[refPic.FrameIdx].FrameIdx;
938                     uint8_t  mbCodeIdx = m_refList[idx]->ucMbCodeIdx;
939                     CODECHAL_ENCODE_CHK_STATUS_RETURN(WaitForRefFrameReady(mbCodeIdx));
940                 }
941             }
942         }
943     }
944 
945     if (!m_firstTwoFrames && m_brcEnabled && m_hevcSeqParams->ParallelBRC)
946     {
947         // When parallel BRC, we still need to wait for the (N-2) PAK
948         CODECHAL_ENCODE_CHK_STATUS_RETURN(WaitForRefFrameReady(m_currMinus2MbCodeIndex));
949         return eStatus;
950     }
951 
952     return eStatus;
953 }
954 
UserFeatureKeyReport()955 MOS_STATUS CodechalEncHevcState::UserFeatureKeyReport()
956 {
957     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
958 
959     CODECHAL_ENCODE_FUNCTION_ENTER;
960 
961     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeHevcBase::UserFeatureKeyReport());
962 
963     CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_REGION_NUMBER_ID, m_numRegionsInSlice);
964 
965     return eStatus;
966 }
967 
InitSurfaceCodecParams2D(CODECHAL_SURFACE_CODEC_PARAMS * params,PMOS_SURFACE surface,uint32_t cacheabilityControl,uint32_t bindingTableOffset,uint32_t verticalLineStride,bool isWritable)968 MOS_STATUS CodechalEncHevcState::InitSurfaceCodecParams2D(
969     CODECHAL_SURFACE_CODEC_PARAMS* params,
970     PMOS_SURFACE surface,
971     uint32_t cacheabilityControl,
972     uint32_t bindingTableOffset,
973     uint32_t verticalLineStride,
974     bool isWritable)
975 {
976     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
977 
978     CODECHAL_ENCODE_FUNCTION_ENTER;
979 
980     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
981 
982     MOS_ZeroMemory(params, sizeof(*params));
983     params->bIs2DSurface = true;
984     params->bMediaBlockRW = true; // Use media block RW for DP 2D surface access
985     params->psSurface = surface;
986     params->dwCacheabilityControl = cacheabilityControl;
987     params->dwBindingTableOffset = bindingTableOffset;
988     params->dwVerticalLineStride = verticalLineStride;
989     params->bIsWritable =
990     params->bRenderTarget = isWritable;
991 
992     return eStatus;
993 }
994 
InitSurfaceCodecParamsVME(CODECHAL_SURFACE_CODEC_PARAMS * params,PMOS_SURFACE surface,uint32_t cacheabilityControl,uint32_t bindingTableOffset)995 MOS_STATUS CodechalEncHevcState::InitSurfaceCodecParamsVME(
996     CODECHAL_SURFACE_CODEC_PARAMS* params,
997     PMOS_SURFACE surface,
998     uint32_t cacheabilityControl,
999     uint32_t bindingTableOffset)
1000 {
1001     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1002 
1003     CODECHAL_ENCODE_FUNCTION_ENTER;
1004 
1005     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
1006 
1007     MOS_ZeroMemory(params, sizeof(*params));
1008     params->bUseAdvState = true;
1009     params->psSurface = surface;
1010     params->dwCacheabilityControl= cacheabilityControl;
1011     params->dwBindingTableOffset = bindingTableOffset;
1012     params->ucVDirection = CODECHAL_VDIRECTION_FRAME;
1013 
1014     // surface has valid values and have support for the formats specified below
1015     if (surface != nullptr && (surface->Format == Format_YUY2V || surface->Format == Format_Y216V))
1016     {
1017         params->dwWidthInUse = surface->dwWidth;
1018         params->dwHeightInUse = surface->dwHeight;
1019     }
1020 
1021     return eStatus;
1022 }
1023 
InitSurfaceCodecParams1D(CODECHAL_SURFACE_CODEC_PARAMS * params,PMOS_RESOURCE buffer,uint32_t size,uint32_t offset,uint32_t cacheabilityControl,uint32_t bindingTableOffset,bool isWritable)1024 MOS_STATUS CodechalEncHevcState::InitSurfaceCodecParams1D(
1025     CODECHAL_SURFACE_CODEC_PARAMS* params,
1026     PMOS_RESOURCE buffer,
1027     uint32_t size,
1028     uint32_t offset,
1029     uint32_t cacheabilityControl,
1030     uint32_t bindingTableOffset,
1031     bool isWritable)
1032 {
1033     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1034 
1035     CODECHAL_ENCODE_FUNCTION_ENTER;
1036 
1037     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
1038 
1039     MOS_ZeroMemory(params, sizeof(*params));
1040     params->presBuffer = buffer;
1041     params->dwSize = size;
1042     params->dwOffset = offset;
1043     params->dwCacheabilityControl = cacheabilityControl;
1044     params->dwBindingTableOffset = bindingTableOffset;
1045     params->bIsWritable =
1046     params->bRenderTarget = isWritable;
1047 
1048     return eStatus;
1049 }
1050 
CodechalEncHevcState(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)1051 CodechalEncHevcState::CodechalEncHevcState(
1052     CodechalHwInterface* hwInterface,
1053     CodechalDebugInterface* debugInterface,
1054     PCODECHAL_STANDARD_INFO standardInfo)
1055     :CodechalEncodeHevcBase(hwInterface, debugInterface, standardInfo)
1056 {
1057     CODECHAL_ENCODE_FUNCTION_ENTER;
1058 
1059     m_noMeKernelForPFrame = true;
1060 
1061     // initialze class members
1062     MOS_ZeroMemory(&m_formatConvertedSurface, sizeof(m_formatConvertedSurface));
1063     MOS_ZeroMemory(&m_brcBuffers, sizeof(m_brcBuffers));
1064 }
1065 
~CodechalEncHevcState()1066 CodechalEncHevcState::~CodechalEncHevcState()
1067 {
1068     MOS_Delete(m_hmeKernel);
1069 }
1070 
AllocateBrcResources()1071 MOS_STATUS CodechalEncHevcState::AllocateBrcResources()
1072 {
1073     CODECHAL_ENCODE_FUNCTION_ENTER;
1074 
1075     // initiate allocation paramters and lock flags
1076     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
1077     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
1078     allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
1079     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
1080     allocParamsForBufferLinear.Format = Format_Buffer;
1081 
1082     MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
1083     MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
1084     allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
1085     allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
1086     allocParamsForBuffer2D.Format = Format_Buffer_2D;
1087 
1088     MOS_LOCK_PARAMS lockFlagsWriteOnly;
1089     MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
1090     lockFlagsWriteOnly.WriteOnly = true;
1091 
1092     // BRC history buffer
1093     uint32_t size = m_brcHistoryBufferSize;
1094     allocParamsForBufferLinear.dwBytes = size;
1095     allocParamsForBufferLinear.pBufName = "BRC History Buffer";
1096 
1097     MOS_STATUS eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1098         m_osInterface,
1099         &allocParamsForBufferLinear,
1100         &m_brcBuffers.resBrcHistoryBuffer);
1101 
1102     if (eStatus != MOS_STATUS_SUCCESS)
1103     {
1104         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate BRC History Buffer.");
1105         return eStatus;
1106     }
1107 
1108     uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
1109         m_osInterface,
1110         &(m_brcBuffers.resBrcHistoryBuffer),
1111         &lockFlagsWriteOnly);
1112 
1113     if (data == nullptr)
1114     {
1115         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock BRC History Buffer.");
1116         eStatus = MOS_STATUS_UNKNOWN;
1117         return eStatus;
1118     }
1119 
1120     MOS_ZeroMemory(data, size);
1121     m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcHistoryBuffer);
1122 
1123     // BRC Intra Distortion Surface
1124     uint32_t width = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x << 3), 64);
1125     uint32_t height = MOS_ALIGN_CEIL((m_downscaledHeightInMb4x << 2), 8) << 1;
1126     allocParamsForBuffer2D.dwWidth = width;
1127     allocParamsForBuffer2D.dwHeight = height;
1128     allocParamsForBuffer2D.pBufName = "BRC Distortion Surface Buffer";
1129 
1130     CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
1131                                                   m_osInterface,
1132                                                   &allocParamsForBuffer2D,
1133                                                   &m_brcBuffers.sBrcIntraDistortionBuffer.OsResource),
1134         "Failed to allocate  ME BRC Distortion Buffer.");
1135 
1136     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, &m_brcBuffers.sBrcIntraDistortionBuffer));
1137     m_brcBuffers.sBrcIntraDistortionBuffer.bArraySpacing = true;
1138     size                                                 = m_brcBuffers.sBrcIntraDistortionBuffer.dwHeight * m_brcBuffers.sBrcIntraDistortionBuffer.dwPitch;
1139 
1140     CODECHAL_ENCODE_CHK_NULL_RETURN(data = (uint8_t *)m_osInterface->pfnLockResource(
1141                                         m_osInterface,
1142                                         &m_brcBuffers.sBrcIntraDistortionBuffer.OsResource,
1143                                         &lockFlagsWriteOnly));
1144 
1145     MOS_ZeroMemory(data, size);
1146     m_osInterface->pfnUnlockResource(
1147         m_osInterface, &m_brcBuffers.sBrcIntraDistortionBuffer.OsResource);
1148 
1149     // PAK Statistics buffer
1150     size                                = m_hevcBrcPakStatisticsSize;
1151     allocParamsForBufferLinear.dwBytes = size;
1152     allocParamsForBufferLinear.pBufName = "BRC PAK Statistics Buffer";
1153 
1154     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1155     {
1156         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1157             m_osInterface,
1158             &allocParamsForBufferLinear,
1159             &m_brcBuffers.resBrcPakStatisticBuffer[i]);
1160 
1161         if (eStatus != MOS_STATUS_SUCCESS)
1162         {
1163             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate BRC PAK Statistics Buffer.");
1164             return eStatus;
1165         }
1166 
1167         data = (uint8_t *)m_osInterface->pfnLockResource(
1168             m_osInterface,
1169             &(m_brcBuffers.resBrcPakStatisticBuffer[i]),
1170             &lockFlagsWriteOnly);
1171 
1172         if (data == nullptr)
1173         {
1174             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock BRC PAK Statistics Buffer.");
1175             eStatus = MOS_STATUS_UNKNOWN;
1176             return eStatus;
1177         }
1178 
1179         MOS_ZeroMemory(data, size);
1180         m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcPakStatisticBuffer[i]);
1181     }
1182 
1183     // PAK HCP_PICTURE_STATEs buffer
1184     size                                = m_brcBuffers.dwBrcHcpPicStateSize;
1185     allocParamsForBufferLinear.dwBytes = size;
1186     allocParamsForBufferLinear.pBufName = "PAK HCP PICTURE State Read Buffer";
1187 
1188     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1189     {
1190         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1191             m_osInterface,
1192             &allocParamsForBufferLinear,
1193             &m_brcBuffers.resBrcImageStatesReadBuffer[i]);
1194 
1195         if (eStatus != MOS_STATUS_SUCCESS)
1196         {
1197             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate HCP PICTURE State Read Buffer.");
1198             return eStatus;
1199         }
1200 
1201         data = (uint8_t *)m_osInterface->pfnLockResource(
1202             m_osInterface,
1203             &(m_brcBuffers.resBrcImageStatesReadBuffer[i]),
1204             &lockFlagsWriteOnly);
1205 
1206         if (data == nullptr)
1207         {
1208             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock HCP PICTURE State Read Buffer.");
1209             eStatus = MOS_STATUS_UNKNOWN;
1210             return eStatus;
1211         }
1212 
1213         MOS_ZeroMemory(data, size);
1214         m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcImageStatesReadBuffer[i]);
1215     }
1216 
1217     allocParamsForBufferLinear.pBufName = "PAK HCP PICTURE State Write Buffer";
1218     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1219     {
1220         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1221             m_osInterface,
1222             &allocParamsForBufferLinear,
1223             &m_brcBuffers.resBrcImageStatesWriteBuffer[i]);
1224 
1225         CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(eStatus, "Failed to allocate HCP PICTURE State Write Buffer.");
1226 
1227         data = (uint8_t *)m_osInterface->pfnLockResource(
1228             m_osInterface,
1229             &m_brcBuffers.resBrcImageStatesWriteBuffer[i],
1230             &lockFlagsWriteOnly);
1231 
1232         if (data == nullptr)
1233         {
1234             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock HCP PICTURE State Write Buffer.");
1235             eStatus = MOS_STATUS_NULL_POINTER;
1236             return eStatus;
1237         }
1238 
1239         MOS_ZeroMemory(data, size);
1240         m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcImageStatesWriteBuffer[i]);
1241     }
1242 
1243     // BRC constant data surface
1244     allocParamsForBuffer2D.dwWidth  = MOS_ALIGN_CEIL(m_brcBuffers.dwBrcConstantSurfaceWidth, 64);
1245     allocParamsForBuffer2D.dwHeight = m_brcBuffers.dwBrcConstantSurfaceHeight;
1246     allocParamsForBuffer2D.pBufName = "BRC Constant Data Buffer";
1247 
1248     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1249     {
1250         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1251             m_osInterface,
1252             &allocParamsForBuffer2D,
1253             &m_brcBuffers.sBrcConstantDataBuffer[i].OsResource);
1254 
1255         if (eStatus != MOS_STATUS_SUCCESS)
1256         {
1257             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate BRC Constant Data Buffer.");
1258             return eStatus;
1259         }
1260 
1261         CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, &m_brcBuffers.sBrcConstantDataBuffer[i]));
1262         m_brcBuffers.sBrcConstantDataBuffer[i].bArraySpacing = true;
1263     }
1264 
1265     // Use the Mb QP buffer in BrcBuffer for LCU-based Qp surface in HEVC
1266     MOS_ZeroMemory(&m_brcBuffers.sBrcMbQpBuffer, sizeof(m_brcBuffers.sBrcMbQpBuffer));
1267 
1268     // original picture size in MB units aligned to 64 bytes along width and 8 bytes along height
1269     width = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * SCALE_FACTOR_4x), 64);
1270     height = MOS_ALIGN_CEIL((m_downscaledHeightInMb4x * SCALE_FACTOR_4x), 8);
1271     size = width * height;
1272 
1273     allocParamsForBuffer2D.dwWidth = width;
1274     allocParamsForBuffer2D.dwHeight = height;
1275     allocParamsForBuffer2D.pBufName = "BRC MB QP Buffer";
1276 
1277     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1278         m_osInterface,
1279         &allocParamsForBuffer2D,
1280         &m_brcBuffers.sBrcMbQpBuffer.OsResource);
1281 
1282     if (eStatus != MOS_STATUS_SUCCESS)
1283     {
1284         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate BRC MB QP Buffer.");
1285         return eStatus;
1286     }
1287 
1288     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, &m_brcBuffers.sBrcMbQpBuffer));
1289     m_brcBuffers.sBrcMbQpBuffer.bArraySpacing = true;
1290 
1291     data = (uint8_t *)m_osInterface->pfnLockResource(
1292         m_osInterface,
1293         &(m_brcBuffers.sBrcMbQpBuffer.OsResource),
1294         &lockFlagsWriteOnly);
1295 
1296     if (data == nullptr)
1297     {
1298         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock BRC MB QP Buffer.");
1299         eStatus = MOS_STATUS_UNKNOWN;
1300         return eStatus;
1301     }
1302 
1303     MOS_ZeroMemory(data, size);
1304     m_osInterface->pfnUnlockResource(
1305         m_osInterface,
1306         &m_brcBuffers.sBrcMbQpBuffer.OsResource);
1307 
1308     // ROI surface
1309     MOS_ZeroMemory(&m_brcBuffers.sBrcRoiSurface, sizeof(m_brcBuffers.sBrcRoiSurface));
1310 
1311     // original picture size in MB units aligned to 64 bytes along width and 8 bytes along height
1312     // ROI buffer size uses MB units for HEVC, not LCU
1313     width = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x << 4), 64);
1314     height = MOS_ALIGN_CEIL((m_downscaledHeightInMb4x << 2), 8);
1315 
1316     MOS_ZeroMemory(&m_brcBuffers.sBrcRoiSurface, sizeof(m_brcBuffers.sBrcRoiSurface));
1317     m_brcBuffers.sBrcRoiSurface.TileType       = MOS_TILE_LINEAR;
1318     m_brcBuffers.sBrcRoiSurface.bArraySpacing  = true;
1319     m_brcBuffers.sBrcRoiSurface.Format         = Format_Buffer_2D;
1320     m_brcBuffers.sBrcRoiSurface.dwWidth        = width;
1321     m_brcBuffers.sBrcRoiSurface.dwPitch        = width;
1322     m_brcBuffers.sBrcRoiSurface.dwHeight       = height;
1323 
1324     CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D(
1325         &m_brcBuffers.sBrcRoiSurface,
1326         width,
1327         height,
1328         "ROI Buffer"));
1329 
1330     return eStatus;
1331 }
1332 
FreeBrcResources()1333 MOS_STATUS CodechalEncHevcState::FreeBrcResources()
1334 {
1335     CODECHAL_ENCODE_FUNCTION_ENTER;
1336 
1337     m_osInterface->pfnFreeResource(
1338         m_osInterface,
1339         &m_brcBuffers.resBrcHistoryBuffer);
1340 
1341     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1342     {
1343         m_osInterface->pfnFreeResource(
1344             m_osInterface,
1345             &m_brcBuffers.resBrcPakStatisticBuffer[i]);
1346 
1347         m_osInterface->pfnFreeResource(
1348             m_osInterface,
1349             &m_brcBuffers.resBrcImageStatesReadBuffer[i]);
1350 
1351         m_osInterface->pfnFreeResource(
1352             m_osInterface,
1353             &m_brcBuffers.resBrcImageStatesWriteBuffer[i]);
1354 
1355         m_osInterface->pfnFreeResource(
1356             m_osInterface,
1357             &m_brcBuffers.sBrcConstantDataBuffer[i].OsResource);
1358     }
1359 
1360     m_osInterface->pfnFreeResource(
1361         m_osInterface,
1362         &m_brcBuffers.sBrcIntraDistortionBuffer.OsResource);
1363 
1364     m_osInterface->pfnFreeResource(
1365         m_osInterface,
1366         &m_brcBuffers.sBrcMbQpBuffer.OsResource);
1367 
1368     m_osInterface->pfnFreeResource(
1369         m_osInterface,
1370         &m_brcBuffers.sBrcRoiSurface.OsResource);
1371 
1372     return MOS_STATUS_SUCCESS;
1373 }
1374 
AllocateEncStatsResources()1375 MOS_STATUS CodechalEncHevcState::AllocateEncStatsResources()
1376 {
1377     CODECHAL_ENCODE_FUNCTION_ENTER;
1378 
1379     if (Mos_ResourceIsNull(&m_encStatsBuffers.m_puStatsSurface.OsResource))
1380     {
1381         CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D(
1382             &m_encStatsBuffers.m_puStatsSurface,
1383             m_widthAlignedMaxLcu,
1384             m_heightAlignedMaxLcu >> 5,
1385             "32x32 PU statistics Data Dump surface"));
1386     }
1387 
1388     if (Mos_ResourceIsNull(&m_encStatsBuffers.m_8x8PuHaarDist.OsResource))
1389     {
1390         CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D(
1391             &m_encStatsBuffers.m_8x8PuHaarDist,
1392             m_widthAlignedMaxLcu,
1393             m_heightAlignedMaxLcu >> 4,
1394             "8x8 PU Haar distortion for 16x16 surface"));
1395     }
1396 
1397     if (Mos_ResourceIsNull(&m_encStatsBuffers.m_8x8PuFrameStats.sResource))
1398     {
1399         CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer(
1400                     &m_encStatsBuffers.m_8x8PuFrameStats,
1401                     m_8x8PuFrameStatsSize,
1402                     "8x8 PU frame statistics surface"));
1403     }
1404 
1405     if (Mos_ResourceIsNull(&m_encStatsBuffers.m_mbEncStatsSurface.OsResource))
1406     {
1407         CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D(
1408             &m_encStatsBuffers.m_mbEncStatsSurface,
1409             m_widthAlignedMaxLcu,
1410             m_heightAlignedMaxLcu >> 5,
1411             "MB Enc Statistics data dump surface"));
1412     }
1413 
1414     if (Mos_ResourceIsNull(&m_encStatsBuffers.m_mbEncFrameStats.sResource))
1415     {
1416         CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer(
1417                     &m_encStatsBuffers.m_mbEncFrameStats,
1418                     m_mbEncFrameStatsSize,
1419                     "MB Enc frame statistics surface"));
1420     }
1421 
1422     return MOS_STATUS_SUCCESS;
1423 }
1424 
FreeEncStatsResources()1425 MOS_STATUS CodechalEncHevcState::FreeEncStatsResources()
1426 {
1427     CODECHAL_ENCODE_FUNCTION_ENTER;
1428 
1429     m_osInterface->pfnFreeResource(
1430             m_osInterface,
1431             &m_encStatsBuffers.m_puStatsSurface.OsResource);
1432 
1433     m_osInterface->pfnFreeResource(
1434             m_osInterface,
1435             &m_encStatsBuffers.m_8x8PuHaarDist.OsResource);
1436 
1437     m_osInterface->pfnFreeResource(
1438             m_osInterface,
1439             &m_encStatsBuffers.m_8x8PuFrameStats.sResource);
1440 
1441     m_osInterface->pfnFreeResource(
1442             m_osInterface,
1443             &m_encStatsBuffers.m_mbEncStatsSurface.OsResource);
1444 
1445     m_osInterface->pfnFreeResource(
1446             m_osInterface,
1447             &m_encStatsBuffers.m_mbEncFrameStats.sResource);
1448 
1449     return MOS_STATUS_SUCCESS;
1450 }
1451 
CheckSupportedFormat(PMOS_SURFACE surface)1452 bool CodechalEncHevcState::CheckSupportedFormat(PMOS_SURFACE surface)
1453 {
1454     CODECHAL_ENCODE_FUNCTION_ENTER;
1455 
1456     bool isColorFormatSupported = false;
1457 
1458     if (nullptr == surface)
1459     {
1460         CODECHAL_ENCODE_ASSERTMESSAGE("Invalid (nullptr) Pointer.");
1461         return isColorFormatSupported;
1462     }
1463 
1464     switch (surface->Format)
1465     {
1466     case Format_NV12:
1467         isColorFormatSupported = IS_Y_MAJOR_TILE_FORMAT(surface->TileType);
1468         break;
1469     case Format_P010:
1470         isColorFormatSupported = true;
1471     case Format_YUY2:
1472     case Format_YUYV:
1473     case Format_A8R8G8B8:
1474         break;
1475     default:
1476         CODECHAL_ENCODE_ASSERTMESSAGE("Input surface color format = %d not supported!", surface->Format);
1477         break;
1478     }
1479 
1480     return isColorFormatSupported;
1481 }
1482 
Initialize(CodechalSetting * settings)1483 MOS_STATUS CodechalEncHevcState::Initialize(CodechalSetting * settings)
1484 {
1485     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1486 
1487     CODECHAL_ENCODE_FUNCTION_ENTER;
1488 
1489     // common initilization
1490     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeHevcBase::Initialize(settings));
1491 
1492     m_brcBuffers.dwBrcHcpPicStateSize       = BRC_IMG_STATE_SIZE_PER_PASS * CODECHAL_ENCODE_BRC_MAXIMUM_NUM_PASSES;
1493     m_brcBuffers.uiCurrBrcPakStasIdxForRead = 0;
1494     //Reading buffer is with 2 frames late for BRC kernel uses the PAK statstic info of the frame before the previous frame
1495     m_brcBuffers.uiCurrBrcPakStasIdxForWrite =
1496         (m_brcBuffers.uiCurrBrcPakStasIdxForRead + 2) % CODECHAL_ENCODE_RECYCLED_BUFFER_NUM;
1497 
1498     m_widthAlignedLcu32  = MOS_ALIGN_CEIL(m_frameWidth, 32);
1499     m_heightAlignedLcu32 = MOS_ALIGN_CEIL(m_frameHeight, 32);
1500 
1501     m_hucCommandsSize = m_hwInterface->m_hucCommandBufferSize * CODECHAL_HEVC_MAX_NUM_BRC_PASSES;
1502 
1503     return eStatus;
1504 }
1505 
GetFrameBrcLevel()1506 MOS_STATUS CodechalEncHevcState::GetFrameBrcLevel()
1507 {
1508     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1509 
1510     CODECHAL_ENCODE_FUNCTION_ENTER;
1511 
1512     if (m_lowDelay)
1513     {
1514         // LDB
1515         if (m_pictureCodingType == I_TYPE)
1516         {
1517             if (m_hevcPicParams->HierarchLevelPlus1 == 0)
1518             {
1519                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_I;
1520             }
1521             else
1522             {
1523                 CODECHAL_ENCODE_ASSERTMESSAGE("FrameLevel can only be 0 for I type for LDB\n");
1524                 return MOS_STATUS_INVALID_PARAMETER;
1525             }
1526         }
1527         else if ((m_pictureCodingType == P_TYPE) || (m_pictureCodingType == B_TYPE))
1528         {
1529             if (m_hevcPicParams->HierarchLevelPlus1 == 0)
1530             {
1531                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_P_OR_LB;
1532             }
1533             else if (m_hevcPicParams->HierarchLevelPlus1 == 1)
1534             {
1535                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_B;
1536             }
1537             else if (m_hevcPicParams->HierarchLevelPlus1 == 2)
1538             {
1539                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_B1;
1540             }
1541             else if (m_hevcPicParams->HierarchLevelPlus1 == 3)
1542             {
1543                 CODECHAL_ENCODE_ASSERTMESSAGE("FrameLevel 3 is not supported for LDB\n");
1544                 return MOS_STATUS_INVALID_PARAMETER;
1545             }
1546             else
1547             {
1548                 CODECHAL_ENCODE_ASSERT(false);
1549                 return MOS_STATUS_INVALID_PARAMETER;
1550             }
1551         }
1552         else if ((m_pictureCodingType == B1_TYPE) || (m_pictureCodingType == B2_TYPE))
1553         {
1554             CODECHAL_ENCODE_ASSERTMESSAGE("B1 & B2 Type is not supported for LDB\n");
1555             return MOS_STATUS_INVALID_PARAMETER;
1556         }
1557         else
1558         {
1559             CODECHAL_ENCODE_ASSERT(false);
1560             return MOS_STATUS_INVALID_PARAMETER;
1561         }
1562     }
1563     else
1564     {
1565         // HB
1566         if (m_pictureCodingType == I_TYPE)
1567         {
1568                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_I;
1569         }
1570         else if (m_pictureCodingType == B_TYPE)
1571         {
1572                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_B;
1573         }
1574         else if (m_pictureCodingType == B1_TYPE)
1575         {
1576                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_B1;
1577         }
1578         else if (m_pictureCodingType == B2_TYPE)
1579         {
1580                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_B2;
1581         }
1582         else if (m_pictureCodingType == P_TYPE)
1583         {
1584                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_P_OR_LB;
1585         }
1586         else
1587         {
1588                 CODECHAL_ENCODE_ASSERT(false);
1589                 return MOS_STATUS_INVALID_PARAMETER;
1590         }
1591     }
1592 
1593     return eStatus;
1594 }
1595 
InitializePicture(const EncoderParams & params)1596 MOS_STATUS CodechalEncHevcState::InitializePicture(const EncoderParams& params)
1597 {
1598     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1599 
1600     CODECHAL_ENCODE_FUNCTION_ENTER;
1601 
1602     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeHevcBase::InitializePicture(params));
1603     CODECHAL_ENCODE_CHK_STATUS_RETURN(GetFrameBrcLevel());
1604 
1605     return eStatus;
1606 }
1607 
SetMeCurbeParams(CodechalKernelHme::CurbeParam & curbeParams)1608 MOS_STATUS CodechalEncHevcState::SetMeCurbeParams(
1609     CodechalKernelHme::CurbeParam &curbeParams)
1610 {
1611     CODECHAL_ENCODE_FUNCTION_ENTER;
1612 
1613     // Setup ME Params
1614     MOS_ZeroMemory(&curbeParams, sizeof(curbeParams));
1615     curbeParams.subPelMode        = 3;
1616     curbeParams.currOriginalPic   = m_hevcPicParams->CurrOriginalPic;
1617     curbeParams.qpPrimeY          = m_hevcPicParams->QpY + m_hevcSliceParams->slice_qp_delta;
1618     curbeParams.targetUsage       = m_hevcSeqParams->TargetUsage;
1619     curbeParams.maxMvLen          = CODECHAL_ENCODE_HEVC_MAX_MV_LEN_AVC_LEVEL_51;
1620     curbeParams.numRefIdxL0Minus1 = m_hevcSliceParams->num_ref_idx_l0_active_minus1;
1621     curbeParams.numRefIdxL1Minus1 = m_hevcSliceParams->num_ref_idx_l1_active_minus1;
1622     curbeParams.bmeMethodTable    = m_bmeMethodTable;
1623     curbeParams.meMethodTable     = m_meMethodTable;
1624 
1625     return MOS_STATUS_SUCCESS;
1626 }
1627 
SetMeSurfaceParams(CodechalKernelHme::SurfaceParams & surfaceParams)1628 MOS_STATUS CodechalEncHevcState::SetMeSurfaceParams(
1629     CodechalKernelHme::SurfaceParams     &surfaceParams)
1630 {
1631     CODECHAL_ENCODE_FUNCTION_ENTER;
1632 
1633     // Setup ME Params
1634     MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams));
1635     surfaceParams.mbaffEnabled                     = false;
1636     surfaceParams.numRefIdxL0ActiveMinus1          = m_hevcSliceParams->num_ref_idx_l0_active_minus1;
1637     surfaceParams.numRefIdxL1ActiveMinus1          = m_hevcSliceParams->num_ref_idx_l1_active_minus1;
1638     surfaceParams.verticalLineStride               = m_verticalLineStride;
1639     surfaceParams.verticalLineStrideOffset         = m_verticalLineStrideOffset;
1640     surfaceParams.meBrcDistortionBuffer            = &m_brcBuffers.sMeBrcDistortionBuffer;
1641     surfaceParams.meBrcDistortionBottomFieldOffset = m_brcBuffers.dwMeBrcDistortionBottomFieldOffset;
1642     surfaceParams.refList                          = &m_refList[0];
1643     surfaceParams.picIdx                           = &m_picIdx[0];
1644     surfaceParams.currOriginalPic                  = &m_currOriginalPic;
1645     surfaceParams.refL0List                        = &(m_hevcSliceParams->RefPicList[LIST_0][0]);
1646     surfaceParams.refL1List                        = &(m_hevcSliceParams->RefPicList[LIST_1][0]);
1647 
1648     return MOS_STATUS_SUCCESS;
1649 }
1650 
EncodeMeKernel()1651 MOS_STATUS CodechalEncHevcState::EncodeMeKernel()
1652 {
1653     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1654 
1655     CODECHAL_ENCODE_FUNCTION_ENTER;
1656 
1657     // Walker must be used for HME call and scaling one
1658     CODECHAL_ENCODE_ASSERT(m_hwWalker);
1659 
1660     if (m_hmeKernel && m_hmeKernel->Is4xMeEnabled())
1661     {
1662         CodechalKernelHme::CurbeParam curbeParam;
1663         CODECHAL_ENCODE_CHK_STATUS_RETURN(SetMeCurbeParams(curbeParam));
1664 
1665         CodechalKernelHme::SurfaceParams surfaceParam;
1666         CODECHAL_ENCODE_CHK_STATUS_RETURN(SetMeSurfaceParams(surfaceParam));
1667         if (m_hmeKernel->Is16xMeEnabled())
1668         {
1669             if (m_hmeKernel->Is32xMeEnabled())
1670             {
1671                 surfaceParam.downScaledWidthInMb         = m_downscaledWidthInMb32x;
1672                 surfaceParam.downScaledHeightInMb        = m_downscaledFrameFieldHeightInMb32x;
1673                 surfaceParam.downScaledBottomFieldOffset = m_scaled32xBottomFieldOffset;
1674                 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hmeKernel->Execute(curbeParam, surfaceParam, CodechalKernelHme::HmeLevel::hmeLevel32x));
1675             }
1676             surfaceParam.downScaledWidthInMb         = m_downscaledWidthInMb16x;
1677             surfaceParam.downScaledHeightInMb        = m_downscaledFrameFieldHeightInMb16x;
1678             surfaceParam.downScaledBottomFieldOffset = m_scaled16xBottomFieldOffset;
1679             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hmeKernel->Execute(curbeParam, surfaceParam, CodechalKernelHme::HmeLevel::hmeLevel16x));
1680         }
1681         surfaceParam.downScaledWidthInMb         = m_downscaledWidthInMb4x;
1682         surfaceParam.downScaledHeightInMb        = m_downscaledFrameFieldHeightInMb4x;
1683         surfaceParam.downScaledBottomFieldOffset = m_scaledBottomFieldOffset;
1684         m_lastTaskInPhase = true;
1685 
1686         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hmeKernel->Execute(curbeParam, surfaceParam, CodechalKernelHme::HmeLevel::hmeLevel4x));
1687     }
1688 
1689     CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpHMESurfaces());
1690 
1691     return eStatus;
1692 }
1693 
DumpHMESurfaces()1694 MOS_STATUS CodechalEncHevcState::DumpHMESurfaces()
1695 {
1696     CODECHAL_ENCODE_FUNCTION_ENTER;
1697 
1698     CODECHAL_DEBUG_TOOL(
1699     if (m_hmeEnabled) {
1700         PMOS_SURFACE dumpBuffer = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me4xMvDataBuffer);
1701         if (dumpBuffer)
1702         {
1703             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
1704                 &dumpBuffer->OsResource,
1705                 CodechalDbgAttr::attrOutput,
1706                 "MvData",
1707                 dumpBuffer->dwHeight *dumpBuffer->dwPitch,
1708                 CodecHal_PictureIsBottomField(m_currOriginalPic) ? MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64) * (m_downscaledFrameFieldHeightInMb4x * 4) : 0,
1709                 CODECHAL_MEDIA_STATE_4X_ME));
1710         }
1711 
1712         dumpBuffer = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me4xDistortionBuffer);
1713         if (dumpBuffer)
1714         {
1715             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
1716                 &dumpBuffer->OsResource,
1717                 CodechalDbgAttr::attrOutput,
1718                 "MeDist",
1719                 dumpBuffer->dwHeight * dumpBuffer->dwPitch,
1720                 CodecHal_PictureIsBottomField(m_currOriginalPic) ? MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64) * MOS_ALIGN_CEIL((m_downscaledFrameFieldHeightInMb4x * 4), 8) : 0,
1721                 CODECHAL_MEDIA_STATE_4X_ME));
1722         }
1723 
1724         if (m_b16XMeEnabled)
1725         {
1726             dumpBuffer = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me16xMvDataBuffer);
1727             //    &meOutputParams));
1728 
1729             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
1730                 &dumpBuffer->OsResource,
1731                 CodechalDbgAttr::attrOutput,
1732                 "MvData",
1733                 dumpBuffer->dwHeight *dumpBuffer->dwPitch,
1734                 CodecHal_PictureIsBottomField(m_currOriginalPic) ? MOS_ALIGN_CEIL((m_downscaledWidthInMb16x * 32), 64) * (m_downscaledFrameFieldHeightInMb16x * 4) : 0,
1735                 CODECHAL_MEDIA_STATE_16X_ME));
1736 
1737             if (m_b32XMeEnabled)
1738             {
1739                 dumpBuffer = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me32xMvDataBuffer);
1740                 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
1741                     &dumpBuffer->OsResource,
1742                     CodechalDbgAttr::attrOutput,
1743                     "MvData",
1744                     dumpBuffer->dwHeight *dumpBuffer->dwPitch,
1745                     CodecHal_PictureIsBottomField(m_currOriginalPic) ? MOS_ALIGN_CEIL((m_downscaledWidthInMb32x * 32), 64) * (m_downscaledFrameFieldHeightInMb32x * 4) : 0,
1746                     CODECHAL_MEDIA_STATE_32X_ME));
1747             }
1748         }
1749     })
1750 
1751     return MOS_STATUS_SUCCESS;
1752 }
1753 
SetupROISurface()1754 MOS_STATUS CodechalEncHevcState::SetupROISurface()
1755 {
1756     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1757 
1758     CODECHAL_ENCODE_FUNCTION_ENTER;
1759 
1760     MOS_LOCK_PARAMS ReadOnly;
1761     MOS_ZeroMemory(&ReadOnly, sizeof(ReadOnly));
1762     ReadOnly.ReadOnly = 1;
1763     uint32_t * dataPtr = (uint32_t *)m_osInterface->pfnLockResource(m_osInterface, &m_brcBuffers.sBrcRoiSurface.OsResource, &ReadOnly);
1764     if (!dataPtr)
1765     {
1766         eStatus = MOS_STATUS_INVALID_HANDLE;
1767         return eStatus;
1768     }
1769 
1770     uint32_t bufferWidthInByte  = m_brcBuffers.sBrcRoiSurface.dwPitch;
1771     uint32_t bufferHeightInByte = MOS_ALIGN_CEIL((m_downscaledHeightInMb4x << 2), 8);
1772     uint32_t numMBs = m_picWidthInMb * m_picHeightInMb;
1773     for (uint32_t uMB = 0; uMB <= numMBs; uMB++)
1774     {
1775         int32_t curMbY = uMB / m_picWidthInMb;
1776         int32_t curMbX = uMB - curMbY * m_picWidthInMb;
1777 
1778         uint32_t outdata = 0;
1779         for (int32_t roiIdx = (m_hevcPicParams->NumROI - 1); roiIdx >= 0; roiIdx--)
1780         {
1781             int32_t qpLevel;
1782             if (m_roiValueInDeltaQp)
1783             {
1784                 qpLevel = m_hevcPicParams->ROI[roiIdx].PriorityLevelOrDQp;
1785             }
1786             else
1787             {
1788                 // QP Level sent to ROI surface is (priority * 5)
1789                 //qpLevel = m_hevcPicParams->ROI[roiIdx].PriorityLevelOrDQp * 6;
1790                 CODECHAL_ENCODE_ASSERTMESSAGE("error: ROI does not support priority level for now.");
1791                 return MOS_STATUS_INVALID_PARAMETER;
1792             }
1793 
1794             if (qpLevel == 0)
1795             {
1796                 continue;
1797             }
1798 
1799             if ((curMbX >= (int32_t)m_hevcPicParams->ROI[roiIdx].Left) && (curMbX < (int32_t)m_hevcPicParams->ROI[roiIdx].Right) &&
1800                 (curMbY >= (int32_t)m_hevcPicParams->ROI[roiIdx].Top) && (curMbY < (int32_t)m_hevcPicParams->ROI[roiIdx].Bottom))
1801             {
1802                 outdata = 15 | ((qpLevel & 0xFF) << 16);
1803             }
1804             else if (m_roiRegionSmoothEnabled)
1805             {
1806                 if ((curMbX >= (int32_t)m_hevcPicParams->ROI[roiIdx].Left - 1) && (curMbX < (int32_t)m_hevcPicParams->ROI[roiIdx].Right + 1) &&
1807                     (curMbY >= (int32_t)m_hevcPicParams->ROI[roiIdx].Top - 1) && (curMbY < (int32_t)m_hevcPicParams->ROI[roiIdx].Bottom + 1))
1808                 {
1809                     outdata = 14 | ((qpLevel & 0xFF) << 16);
1810                 }
1811                 else if ((curMbX >= (int32_t)m_hevcPicParams->ROI[roiIdx].Left - 2) && (curMbX < (int32_t)m_hevcPicParams->ROI[roiIdx].Right + 2) &&
1812                          (curMbY >= (int32_t)m_hevcPicParams->ROI[roiIdx].Top - 2) && (curMbY < (int32_t)m_hevcPicParams->ROI[roiIdx].Bottom + 2))
1813                 {
1814                     outdata = 13 | ((qpLevel & 0xFF) << 16);
1815                 }
1816                 else if ((curMbX >= (int32_t)m_hevcPicParams->ROI[roiIdx].Left - 3) && (curMbX < (int32_t)m_hevcPicParams->ROI[roiIdx].Right + 3) &&
1817                          (curMbY >= (int32_t)m_hevcPicParams->ROI[roiIdx].Top - 3) && (curMbY < (int32_t)m_hevcPicParams->ROI[roiIdx].Bottom + 3))
1818                 {
1819                     outdata = 12 | ((qpLevel & 0xFF) << 16);
1820                 }
1821             }
1822         }
1823         dataPtr[(curMbY * (bufferWidthInByte >> 2)) + curMbX] = outdata;
1824     }
1825 
1826     m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.sBrcRoiSurface.OsResource);
1827 
1828     uint32_t bufferSize = bufferWidthInByte * bufferHeightInByte;
1829     CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
1830         &m_brcBuffers.sBrcRoiSurface.OsResource,
1831         CodechalDbgAttr::attrROISurface,
1832         "ROIInputSurface",
1833         bufferSize,
1834         0,
1835         CODECHAL_NUM_MEDIA_STATES)));
1836 
1837     return eStatus;
1838 }
1839 
GetRoundingIntraInterToUse()1840 MOS_STATUS CodechalEncHevcState::GetRoundingIntraInterToUse()
1841 {
1842     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1843 
1844     CODECHAL_ENCODE_FUNCTION_ENTER;
1845 
1846     if (m_hevcPicParams->CustomRoundingOffsetsParams.fields.EnableCustomRoudingIntra)
1847     {
1848         m_roundingIntraInUse = m_hevcPicParams->CustomRoundingOffsetsParams.fields.RoundingOffsetIntra;
1849     }
1850     else
1851     {
1852         if (m_hevcSeqParams->NumOfBInGop[1] != 0 || m_hevcSeqParams->NumOfBInGop[2] != 0)
1853         {
1854             //Hierachical B GOP
1855             if (m_hevcPicParams->CodingType == I_TYPE ||
1856                 m_hevcPicParams->CodingType == P_TYPE)
1857             {
1858                 m_roundingIntraInUse = 4;
1859             }
1860             else if (m_hevcPicParams->CodingType == B_TYPE)
1861             {
1862                 m_roundingIntraInUse = 3;
1863             }
1864             else
1865             {
1866                 m_roundingIntraInUse = 2;
1867             }
1868         }
1869         else
1870         {
1871             m_roundingIntraInUse = 10;
1872         }
1873     }
1874 
1875     if (m_hevcPicParams->CustomRoundingOffsetsParams.fields.EnableCustomRoudingInter)
1876     {
1877         m_roundingInterInUse = m_hevcPicParams->CustomRoundingOffsetsParams.fields.RoundingOffsetInter;
1878     }
1879     else
1880     {
1881         if (m_hevcSeqParams->NumOfBInGop[1] != 0 || m_hevcSeqParams->NumOfBInGop[2] != 0)
1882         {
1883             //Hierachical B GOP
1884             if (m_hevcPicParams->CodingType == I_TYPE ||
1885                 m_hevcPicParams->CodingType == P_TYPE)
1886             {
1887                 m_roundingInterInUse = 4;
1888             }
1889             else if (m_hevcPicParams->CodingType == B_TYPE)
1890             {
1891                 m_roundingInterInUse = 3;
1892             }
1893             else
1894             {
1895                 m_roundingInterInUse = 2;
1896             }
1897         }
1898         else
1899         {
1900             m_roundingInterInUse = 4;
1901         }
1902     }
1903 
1904     return eStatus;
1905 }
1906 
1907