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         CODECHAL_ENCODE_CHK_NULL_RETURN(mmioRegisters);
442         MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
443         MHW_MI_COPY_MEM_MEM_PARAMS miCpyMemMemParams;
444         // Write back the HCP image control register for RC6 may clean it out
445         MHW_MI_LOAD_REGISTER_MEM_PARAMS miLoadRegMemParams;
446         MOS_ZeroMemory(&miLoadRegMemParams, sizeof(miLoadRegMemParams));
447         miLoadRegMemParams.presStoreBuffer = &m_encodeStatusBuf.resStatusBuffer;
448         miLoadRegMemParams.dwOffset = baseOffset + m_encodeStatusBuf.dwImageStatusCtrlOffset;
449         miLoadRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusCtrlRegOffset;
450         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(&cmdBuffer, &miLoadRegMemParams));
451 
452         MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
453         miStoreRegMemParams.presStoreBuffer = &m_brcBuffers.resBrcPakStatisticBuffer[m_brcBuffers.uiCurrBrcPakStasIdxForWrite];
454         miStoreRegMemParams.dwOffset = CODECHAL_OFFSETOF(CODECHAL_ENCODE_HEVC_PAK_STATS_BUFFER, HCP_IMAGE_STATUS_CONTROL_FOR_LAST_PASS);
455         miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusCtrlRegOffset;
456         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(&cmdBuffer, &miStoreRegMemParams));
457 
458         MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
459         miStoreRegMemParams.presStoreBuffer =  &m_encodeStatusBuf.resStatusBuffer;
460         miStoreRegMemParams.dwOffset = baseOffset + m_encodeStatusBuf.dwImageStatusCtrlOfLastBRCPassOffset;
461         miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusCtrlRegOffset;
462         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(&cmdBuffer, &miStoreRegMemParams));
463     }
464 
465     if (IsFirstPass() && m_osInterface->bTagResourceSync)
466     {
467         // 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
468         // which may be skipped in multi-pass PAK enabled case. The idea here is to insert the previous frame's tag at the beginning
469         // 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
470         // as long as Dec/VP/Enc won't depend on this PAK so soon.
471 
472         PMOS_RESOURCE globalGpuContextSyncTagBuffer = nullptr;
473         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetGpuStatusBufferResource(
474             m_osInterface,
475             globalGpuContextSyncTagBuffer));
476         CODECHAL_ENCODE_CHK_NULL_RETURN(globalGpuContextSyncTagBuffer);
477 
478         MHW_MI_STORE_DATA_PARAMS params;
479         params.pOsResource = globalGpuContextSyncTagBuffer;
480         params.dwResourceOffset = m_osInterface->pfnGetGpuStatusTagOffset(m_osInterface, m_osInterface->CurrentGpuContextOrdinal);
481         uint32_t value = m_osInterface->pfnGetGpuStatusTag(m_osInterface, m_osInterface->CurrentGpuContextOrdinal);
482         params.dwValue = (value > 0) ? (value - 1) : 0;
483         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(&cmdBuffer, &params));
484     }
485 
486     CODECHAL_ENCODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES));
487 
488     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPipeModeSelectCmd(&cmdBuffer));
489 
490     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpSurfaceStateCmds(&cmdBuffer));
491 
492     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPipeBufAddrCmd(&cmdBuffer));
493 
494     MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams;
495     SetHcpIndObjBaseAddrParams(indObjBaseAddrParams);
496     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpIndObjBaseAddrCmd(&cmdBuffer, &indObjBaseAddrParams));
497 
498     MHW_VDBOX_QM_PARAMS fqmParams, qmParams;
499     SetHcpQmStateParams(fqmParams, qmParams);
500     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpFqmStateCmd(&cmdBuffer, &fqmParams));
501     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpQmStateCmd(&cmdBuffer, &qmParams));
502 
503     if (m_brcEnabled)
504     {
505         if (m_hevcSeqParams->SAO_enabled_flag && m_currPass == m_uc2NdSaoPass)
506         {
507             CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPictureStateCmd(&cmdBuffer));
508         }
509         else
510         {
511             uint32_t picStateCmdOffset;
512             picStateCmdOffset = GetCurrentPass();
513 
514             MHW_BATCH_BUFFER batchBuffer;
515             MOS_ZeroMemory(&batchBuffer, sizeof(batchBuffer));
516             batchBuffer.OsResource = m_brcBuffers.resBrcImageStatesWriteBuffer[m_currRecycledBufIdx];
517             batchBuffer.dwOffset = picStateCmdOffset * (m_brcBuffers.dwBrcHcpPicStateSize / CODECHAL_ENCODE_BRC_MAXIMUM_NUM_PASSES);
518             batchBuffer.bSecondLevel = true;
519 
520             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(
521                 &cmdBuffer,
522                 &batchBuffer));
523         }
524     }
525     else
526     {
527         CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPictureStateCmd(&cmdBuffer));
528     }
529 
530     // Send HEVC_VP9_RDOQ_STATE command
531     if (m_hevcRdoqEnabled)
532     {
533         MHW_VDBOX_HEVC_PIC_STATE picStateParams;
534         SetHcpPicStateParams(picStateParams);
535 
536         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpHevcVp9RdoqStateCmd(&cmdBuffer, &picStateParams));
537     }
538 
539     CODECHAL_ENCODE_CHK_STATUS_RETURN(ReturnCommandBuffer(&cmdBuffer));
540 
541     return eStatus;
542 }
543 
AddHcpWeightOffsetStateCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PCODEC_HEVC_ENCODE_SLICE_PARAMS hevcSlcParams)544 MOS_STATUS CodechalEncHevcState::AddHcpWeightOffsetStateCmd(
545     PMOS_COMMAND_BUFFER             cmdBuffer,
546     PMHW_BATCH_BUFFER               batchBuffer,
547     PCODEC_HEVC_ENCODE_SLICE_PARAMS hevcSlcParams)
548 {
549     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
550 
551     CODECHAL_ENCODE_FUNCTION_ENTER;
552 
553     CODECHAL_ENCODE_CHK_NULL_RETURN(hevcSlcParams);
554 
555     if (cmdBuffer == nullptr && batchBuffer == nullptr)
556     {
557         CODECHAL_ENCODE_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
558         return MOS_STATUS_NULL_POINTER;
559     }
560 
561     MHW_VDBOX_HEVC_WEIGHTOFFSET_PARAMS hcpWeightOffsetParams;
562     MOS_ZeroMemory(&hcpWeightOffsetParams, sizeof(hcpWeightOffsetParams));
563 
564     for (auto k = 0; k < 2; k++) // k=0: LIST_0, k=1: LIST_1
565     {
566         // Luma, Chroma offset
567         for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
568         {
569             hcpWeightOffsetParams.LumaOffsets[k][i] = (int16_t)hevcSlcParams->luma_offset[k][i];
570             // Cb, Cr
571             for (auto j = 0; j < 2; j++)
572             {
573                 hcpWeightOffsetParams.ChromaOffsets[k][i][j] = (int16_t)hevcSlcParams->chroma_offset[k][i][j];
574             }
575         }
576 
577         // Luma Weight
578         CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(
579             &hcpWeightOffsetParams.LumaWeights[k],
580             sizeof(hcpWeightOffsetParams.LumaWeights[k]),
581             &hevcSlcParams->delta_luma_weight[k],
582             sizeof(hevcSlcParams->delta_luma_weight[k])));
583 
584         // Chroma Weight
585         CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(
586             &hcpWeightOffsetParams.ChromaWeights[k],
587             sizeof(hcpWeightOffsetParams.ChromaWeights[k]),
588             &hevcSlcParams->delta_chroma_weight[k],
589             sizeof(hevcSlcParams->delta_chroma_weight[k])));
590     }
591 
592     if (hevcSlcParams->slice_type == CODECHAL_ENCODE_HEVC_P_SLICE || hevcSlcParams->slice_type == CODECHAL_ENCODE_HEVC_B_SLICE)
593     {
594         hcpWeightOffsetParams.ucList = LIST_0;
595         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpWeightOffsetStateCmd(cmdBuffer, batchBuffer, &hcpWeightOffsetParams));
596     }
597 
598     if (hevcSlcParams->slice_type == CODECHAL_ENCODE_HEVC_B_SLICE)
599     {
600         hcpWeightOffsetParams.ucList = LIST_1;
601         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpWeightOffsetStateCmd(cmdBuffer, batchBuffer, &hcpWeightOffsetParams));
602     }
603 
604     return eStatus;
605 }
606 
607 //------------------------------------------------------------------------------------
608 // Build slices with header insertion
609 //------------------------------------------------------------------------------------
SendHwSliceEncodeCommand(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_HEVC_SLICE_STATE params)610 MOS_STATUS CodechalEncHevcState::SendHwSliceEncodeCommand(
611     PMOS_COMMAND_BUFFER             cmdBuffer,
612     PMHW_VDBOX_HEVC_SLICE_STATE     params)
613 {
614     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
615 
616     CODECHAL_ENCODE_FUNCTION_ENTER;
617 
618     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
619     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pHevcPicIdx);
620     CODECHAL_ENCODE_CHK_NULL_RETURN(params->presDataBuffer);
621     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeHevcSeqParams);
622     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeHevcPicParams);
623     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeHevcSliceParams);
624     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
625     CODECHAL_ENCODE_CHK_NULL_RETURN(params->ppNalUnitParams);
626 
627     PMHW_BATCH_BUFFER batchBufferInUse = nullptr;
628     PMOS_COMMAND_BUFFER cmdBufferInUse = nullptr;
629 
630     if (params->bSingleTaskPhaseSupported)
631     {
632         CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBatchBufferForPakSlices);
633         batchBufferInUse = params->pBatchBufferForPakSlices;
634     }
635     else
636     {
637         cmdBufferInUse = cmdBuffer;
638     }
639 
640     // add HCP_REF_IDX command
641     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpRefIdxCmd(cmdBufferInUse, batchBufferInUse, params));
642 
643     if (params->bWeightedPredInUse)
644     {
645         //add weghtoffset command
646         CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpWeightOffsetStateCmd(cmdBufferInUse, batchBufferInUse, m_hevcSliceParams));
647     }
648 
649     // add HEVC Slice state commands
650     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpSliceStateCmd(cmdBufferInUse, params));
651 
652     // add HCP_PAK_INSERT_OBJECTS command
653     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPakInsertNALUs(cmdBufferInUse, batchBufferInUse, params));
654 
655     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddHcpPakInsertSliceHeader(cmdBufferInUse, batchBufferInUse, params));
656 
657     if (params->bSingleTaskPhaseSupported && batchBufferInUse)
658     {
659         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(nullptr, batchBufferInUse));
660 
661         MHW_BATCH_BUFFER secondLevelBatchBuffer;
662         MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(MHW_BATCH_BUFFER));
663         secondLevelBatchBuffer.OsResource = batchBufferInUse->OsResource;
664         secondLevelBatchBuffer.dwOffset = params->dwBatchBufferForPakSlicesStartOffset;
665         secondLevelBatchBuffer.bSecondLevel = true;
666         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(cmdBuffer, &secondLevelBatchBuffer));
667     }
668 
669     // Insert Batch Buffer Start command to send HCP_PAK_OBJ data for LCUs in this slice
670     MHW_BATCH_BUFFER secondLevelBatchBuffer;
671     MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(MHW_BATCH_BUFFER));
672     secondLevelBatchBuffer.OsResource = *params->presDataBuffer;
673     secondLevelBatchBuffer.dwOffset = params->dwDataBufferOffset;
674     secondLevelBatchBuffer.bSecondLevel = true;
675     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(cmdBuffer, &secondLevelBatchBuffer));
676 
677     return eStatus;
678 }
679 
ExecuteSliceLevel()680 MOS_STATUS CodechalEncHevcState::ExecuteSliceLevel()
681 {
682     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
683 
684     CODECHAL_ENCODE_FUNCTION_ENTER;
685 
686     CODECHAL_ENCODE_CHK_NULL_RETURN(m_slcData);
687     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetBatchBufferForPakSlices());
688 
689     MOS_COMMAND_BUFFER cmdBuffer;
690     CODECHAL_ENCODE_CHK_STATUS_RETURN(GetCommandBuffer(&cmdBuffer));
691 
692     SetHcpSliceStateCommonParams(*m_sliceStateParams);
693 
694     PCODEC_ENCODER_SLCDATA slcData = m_slcData;
695     for (uint32_t startLCU = 0, SlcCount = 0; SlcCount < m_numSlices; SlcCount++)
696     {
697         if (m_currPass == 0)
698         {
699             slcData[SlcCount].CmdOffset = startLCU * (m_hcpInterface->GetHcpPakObjSize()) * sizeof(uint32_t);
700         }
701 
702         SetHcpSliceStateParams(*m_sliceStateParams, slcData, SlcCount);
703 
704         CODECHAL_ENCODE_CHK_STATUS_RETURN(SendHwSliceEncodeCommand(&cmdBuffer, m_sliceStateParams));
705 
706         startLCU += m_hevcSliceParams[SlcCount].NumLCUsInSlice;
707 
708         m_batchBufferForPakSlicesStartOffset =
709             (uint32_t)m_batchBufferForPakSlices[m_currPakSliceIdx].iCurrent;
710     }
711 
712     if (m_useBatchBufferForPakSlices)
713     {
714         CODECHAL_ENCODE_CHK_STATUS_RETURN(Mhw_UnlockBb(
715             m_osInterface,
716             &m_batchBufferForPakSlices[m_currPakSliceIdx],
717             m_lastTaskInPhase));
718     }
719 
720     // Insert end of sequence/stream if set
721     if (m_lastPicInStream || m_lastPicInSeq)
722     {
723         MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams;
724         MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams));
725         pakInsertObjectParams.bLastPicInSeq     = m_lastPicInSeq;
726         pakInsertObjectParams.bLastPicInStream  = m_lastPicInStream;
727         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPakInsertObject(&cmdBuffer, &pakInsertObjectParams));
728     }
729 
730     CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadHcpStatus(&cmdBuffer));
731 
732     // BRC PAK statistics different for each pass
733     if (m_brcEnabled)
734     {
735         CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadBrcPakStats(&cmdBuffer));
736     }
737 
738     if (!Mos_ResourceIsNull(&m_resFrameStatStreamOutBuffer))
739     {
740         CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadSseStatistics(&cmdBuffer));
741     }
742 
743     CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES));
744 
745     if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
746     {
747         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
748     }
749 
750     std::string pakPassName = "PAK_PASS" + std::to_string(static_cast<uint32_t>(m_currPass));
751     CODECHAL_DEBUG_TOOL(
752         CODECHAL_ENCODE_CHK_STATUS_RETURN( m_debugInterface->DumpCmdBuffer(
753             &cmdBuffer,
754             CODECHAL_NUM_MEDIA_STATES,
755             pakPassName.data()));)
756 
757     CODECHAL_ENCODE_CHK_STATUS_RETURN(ReturnCommandBuffer(&cmdBuffer));
758 
759     if ((!m_pakOnlyTest) &&  // In the PAK only test, no need to wait for ENC's completion
760         (m_currPass == 0) &&
761         !Mos_ResourceIsNull(&m_resSyncObjectRenderContextInUse))
762     {
763         MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
764         syncParams.GpuContext = m_videoContext;
765         syncParams.presSyncResource = &m_resSyncObjectRenderContextInUse;
766 
767         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
768     }
769 
770     bool renderingFlags = m_videoContextUsesNullHw;
771 
772     if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
773     {
774         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, renderingFlags));
775 
776         CODECHAL_DEBUG_TOOL(
777             if (m_mmcState)
778             {
779                 m_mmcState->UpdateUserFeatureKey(&m_reconSurface);
780             }
781         )
782 
783         if ((m_currPass == m_numPasses) &&
784             m_signalEnc &&
785             m_currRefSync &&
786             !Mos_ResourceIsNull(&m_currRefSync->resSyncObject))
787         {
788             // signal semaphore
789             MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
790             syncParams.GpuContext = m_videoContext;
791             syncParams.presSyncResource = &m_currRefSync->resSyncObject;
792 
793             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
794             m_currRefSync->uiSemaphoreObjCount++;
795             m_currRefSync->bInUsed = true;
796         }
797     }
798 
799     // Reset parameters for next PAK execution
800     if (m_currPass == m_numPasses)
801     {
802         if (!m_singleTaskPhaseSupported)
803         {
804             m_osInterface->pfnResetPerfBufferID(m_osInterface);
805         }
806 
807         m_currPakSliceIdx = (m_currPakSliceIdx + 1) % CODECHAL_HEVC_NUM_PAK_SLICE_BATCH_BUFFERS;
808 
809         if (m_hevcSeqParams->ParallelBRC)
810         {
811             m_brcBuffers.uiCurrBrcPakStasIdxForWrite =
812                 (m_brcBuffers.uiCurrBrcPakStasIdxForWrite + 1) % CODECHAL_ENCODE_RECYCLED_BUFFER_NUM;
813         }
814 
815         m_newPpsHeader = 0;
816         m_newSeqHeader = 0;
817         m_frameNum++;
818     }
819 
820     return eStatus;
821 }
822 
823 //------------------------------------------------------------------------------
824 //| Purpose:    Retrieves the HCP registers and stores them in the status report
825 //| Return:     N/A
826 //------------------------------------------------------------------------------
ReadHcpStatus(PMOS_COMMAND_BUFFER cmdBuffer)827 MOS_STATUS CodechalEncHevcState::ReadHcpStatus(PMOS_COMMAND_BUFFER cmdBuffer)
828 {
829     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
830 
831     CODECHAL_ENCODE_FUNCTION_ENTER;
832 
833     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
834 
835     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeHevcBase::ReadHcpStatus(cmdBuffer));
836 
837     CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadImageStatus(cmdBuffer))
838 
839     return eStatus;
840 }
841 
CalculateROIRatio()842 uint8_t CodechalEncHevcState::CalculateROIRatio()
843 {
844     uint32_t roiSize = 0;
845     for (uint32_t i = 0; i < m_hevcPicParams->NumROI; ++i)
846     {
847         roiSize += (ENCODE_DP_HEVC_ROI_BLOCK_Width * (MOS_ABS(m_hevcPicParams->ROI[i].Top - m_hevcPicParams->ROI[i].Bottom) + 1 )) *
848                    (ENCODE_DP_HEVC_ROI_BLOCK_HEIGHT * (MOS_ABS(m_hevcPicParams->ROI[i].Right - m_hevcPicParams->ROI[i].Left) + 1));
849     }
850 
851     uint32_t roiRatio = 0;
852     if (roiSize)
853     {
854         uint32_t numMBs = m_picWidthInMb * m_picHeightInMb;
855         roiRatio = 2 * (numMBs * 256 / roiSize - 1);
856         roiRatio = MOS_MIN(51, roiRatio);
857     }
858 
859     return (uint8_t)roiRatio;
860 }
861 
ComputeTemporalDifference(const CODEC_PICTURE & refPic)862 int16_t CodechalEncHevcState::ComputeTemporalDifference(const CODEC_PICTURE& refPic)
863 {
864     int16_t diff_poc = 0;
865 
866     if (!CodecHal_PictureIsInvalid(refPic))
867     {
868         diff_poc = m_hevcPicParams->CurrPicOrderCnt - m_hevcPicParams->RefFramePOCList[refPic.FrameIdx];
869 
870         if(diff_poc < -128)
871         {
872             diff_poc = -128;
873         }
874         else if(diff_poc > 127)
875         {
876             diff_poc = 127;
877         }
878     }
879 
880     return diff_poc;
881 }
882 
WaitForRefFrameReady(uint8_t mbCodeIdx)883 MOS_STATUS CodechalEncHevcState::WaitForRefFrameReady(uint8_t mbCodeIdx)
884 {
885     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
886 
887     CODECHAL_ENCODE_FUNCTION_ENTER;
888 
889     if (!m_refSync[mbCodeIdx].bInUsed)
890     {
891         return eStatus;
892     }
893 
894     MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
895     syncParams.GpuContext = m_renderContext;
896     syncParams.presSyncResource = &m_refSync[mbCodeIdx].resSyncObject;
897     syncParams.uiSemaphoreCount = m_refSync[mbCodeIdx].uiSemaphoreObjCount;
898 
899     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
900     m_refSync[mbCodeIdx].uiSemaphoreObjCount = 0;
901     m_refSync[mbCodeIdx].bInUsed             = false;
902 
903     return eStatus;
904 }
905 
WaitForPak()906 MOS_STATUS CodechalEncHevcState::WaitForPak()
907 {
908     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
909 
910     CODECHAL_ENCODE_FUNCTION_ENTER;
911 
912     if (m_pictureCodingType == I_TYPE && !m_brcEnabled)
913     {
914         return eStatus;
915     }
916 
917     if (!m_firstFrame && m_brcEnabled && !m_hevcSeqParams->ParallelBRC)
918     {
919         // When there is no parallel BRC, we still need to wait for previous PAK
920         CODECHAL_ENCODE_CHK_STATUS_RETURN(WaitForRefFrameReady(m_lastMbCodeIndex));
921         return eStatus;
922     }
923 
924     // 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.
925     auto slcParams = m_hevcSliceParams;
926     for (uint32_t s = 0; s < m_numSlices; s++, slcParams++)
927     {
928         for (auto ll = 0; ll < 2; ll++)
929         {
930             uint32_t uiNumRef = (ll == 0) ? slcParams->num_ref_idx_l0_active_minus1 :
931                 slcParams->num_ref_idx_l1_active_minus1;
932 
933             for (uint32_t i = 0; i <= uiNumRef; i++)
934             {
935                 CODEC_PICTURE refPic = slcParams->RefPicList[ll][i];
936                 if (!CodecHal_PictureIsInvalid(refPic) &&
937                     !CodecHal_PictureIsInvalid(m_hevcPicParams->RefFrameList[refPic.FrameIdx]))
938                 {
939                     uint32_t idx       = m_hevcPicParams->RefFrameList[refPic.FrameIdx].FrameIdx;
940                     uint8_t  mbCodeIdx = m_refList[idx]->ucMbCodeIdx;
941                     CODECHAL_ENCODE_CHK_STATUS_RETURN(WaitForRefFrameReady(mbCodeIdx));
942                 }
943             }
944         }
945     }
946 
947     if (!m_firstTwoFrames && m_brcEnabled && m_hevcSeqParams->ParallelBRC)
948     {
949         // When parallel BRC, we still need to wait for the (N-2) PAK
950         CODECHAL_ENCODE_CHK_STATUS_RETURN(WaitForRefFrameReady(m_currMinus2MbCodeIndex));
951         return eStatus;
952     }
953 
954     return eStatus;
955 }
956 
UserFeatureKeyReport()957 MOS_STATUS CodechalEncHevcState::UserFeatureKeyReport()
958 {
959     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
960 
961     CODECHAL_ENCODE_FUNCTION_ENTER;
962 
963     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeHevcBase::UserFeatureKeyReport());
964 
965     CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_REGION_NUMBER_ID, m_numRegionsInSlice, m_osInterface->pOsContext);
966 
967     return eStatus;
968 }
969 
InitSurfaceCodecParams2D(CODECHAL_SURFACE_CODEC_PARAMS * params,PMOS_SURFACE surface,uint32_t cacheabilityControl,uint32_t bindingTableOffset,uint32_t verticalLineStride,bool isWritable)970 MOS_STATUS CodechalEncHevcState::InitSurfaceCodecParams2D(
971     CODECHAL_SURFACE_CODEC_PARAMS* params,
972     PMOS_SURFACE surface,
973     uint32_t cacheabilityControl,
974     uint32_t bindingTableOffset,
975     uint32_t verticalLineStride,
976     bool isWritable)
977 {
978     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
979 
980     CODECHAL_ENCODE_FUNCTION_ENTER;
981 
982     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
983 
984     MOS_ZeroMemory(params, sizeof(*params));
985     params->bIs2DSurface = true;
986     params->bMediaBlockRW = true; // Use media block RW for DP 2D surface access
987     params->psSurface = surface;
988     params->dwCacheabilityControl = cacheabilityControl;
989     params->dwBindingTableOffset = bindingTableOffset;
990     params->dwVerticalLineStride = verticalLineStride;
991     params->bIsWritable =
992     params->bRenderTarget = isWritable;
993 
994     return eStatus;
995 }
996 
InitSurfaceCodecParamsVME(CODECHAL_SURFACE_CODEC_PARAMS * params,PMOS_SURFACE surface,uint32_t cacheabilityControl,uint32_t bindingTableOffset)997 MOS_STATUS CodechalEncHevcState::InitSurfaceCodecParamsVME(
998     CODECHAL_SURFACE_CODEC_PARAMS* params,
999     PMOS_SURFACE surface,
1000     uint32_t cacheabilityControl,
1001     uint32_t bindingTableOffset)
1002 {
1003     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1004 
1005     CODECHAL_ENCODE_FUNCTION_ENTER;
1006 
1007     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
1008 
1009     MOS_ZeroMemory(params, sizeof(*params));
1010     params->bUseAdvState = true;
1011     params->psSurface = surface;
1012     params->dwCacheabilityControl= cacheabilityControl;
1013     params->dwBindingTableOffset = bindingTableOffset;
1014     params->ucVDirection = CODECHAL_VDIRECTION_FRAME;
1015 
1016     // surface has valid values and have support for the formats specified below
1017     if (surface != nullptr && (surface->Format == Format_YUY2V || surface->Format == Format_Y216V))
1018     {
1019         params->dwWidthInUse = surface->dwWidth;
1020         params->dwHeightInUse = surface->dwHeight;
1021     }
1022 
1023     return eStatus;
1024 }
1025 
InitSurfaceCodecParams1D(CODECHAL_SURFACE_CODEC_PARAMS * params,PMOS_RESOURCE buffer,uint32_t size,uint32_t offset,uint32_t cacheabilityControl,uint32_t bindingTableOffset,bool isWritable)1026 MOS_STATUS CodechalEncHevcState::InitSurfaceCodecParams1D(
1027     CODECHAL_SURFACE_CODEC_PARAMS* params,
1028     PMOS_RESOURCE buffer,
1029     uint32_t size,
1030     uint32_t offset,
1031     uint32_t cacheabilityControl,
1032     uint32_t bindingTableOffset,
1033     bool isWritable)
1034 {
1035     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1036 
1037     CODECHAL_ENCODE_FUNCTION_ENTER;
1038 
1039     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
1040 
1041     MOS_ZeroMemory(params, sizeof(*params));
1042     params->presBuffer = buffer;
1043     params->dwSize = size;
1044     params->dwOffset = offset;
1045     params->dwCacheabilityControl = cacheabilityControl;
1046     params->dwBindingTableOffset = bindingTableOffset;
1047     params->bIsWritable =
1048     params->bRenderTarget = isWritable;
1049 
1050     return eStatus;
1051 }
1052 
CodechalEncHevcState(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)1053 CodechalEncHevcState::CodechalEncHevcState(
1054     CodechalHwInterface* hwInterface,
1055     CodechalDebugInterface* debugInterface,
1056     PCODECHAL_STANDARD_INFO standardInfo)
1057     :CodechalEncodeHevcBase(hwInterface, debugInterface, standardInfo)
1058 {
1059     CODECHAL_ENCODE_FUNCTION_ENTER;
1060 
1061     m_noMeKernelForPFrame = true;
1062 
1063     // initialze class members
1064     MOS_ZeroMemory(&m_formatConvertedSurface, sizeof(m_formatConvertedSurface));
1065     MOS_ZeroMemory(&m_brcBuffers, sizeof(m_brcBuffers));
1066 }
1067 
~CodechalEncHevcState()1068 CodechalEncHevcState::~CodechalEncHevcState()
1069 {
1070     if (m_hmeKernel)
1071     {
1072         MOS_Delete(m_hmeKernel);
1073         m_hmeKernel = nullptr;
1074     }
1075 }
1076 
AllocateBrcResources()1077 MOS_STATUS CodechalEncHevcState::AllocateBrcResources()
1078 {
1079     CODECHAL_ENCODE_FUNCTION_ENTER;
1080 
1081     // initiate allocation paramters and lock flags
1082     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
1083     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
1084     allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
1085     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
1086     allocParamsForBufferLinear.Format = Format_Buffer;
1087 
1088     MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
1089     MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
1090     allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
1091     allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
1092     allocParamsForBuffer2D.Format = Format_Buffer_2D;
1093 
1094     MOS_LOCK_PARAMS lockFlagsWriteOnly;
1095     MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
1096     lockFlagsWriteOnly.WriteOnly = true;
1097 
1098     // BRC history buffer
1099     uint32_t size = m_brcHistoryBufferSize;
1100     allocParamsForBufferLinear.dwBytes = size;
1101     allocParamsForBufferLinear.pBufName = "BRC History Buffer";
1102 
1103     MOS_STATUS eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1104         m_osInterface,
1105         &allocParamsForBufferLinear,
1106         &m_brcBuffers.resBrcHistoryBuffer);
1107 
1108     if (eStatus != MOS_STATUS_SUCCESS)
1109     {
1110         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate BRC History Buffer.");
1111         return eStatus;
1112     }
1113 
1114     uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
1115         m_osInterface,
1116         &(m_brcBuffers.resBrcHistoryBuffer),
1117         &lockFlagsWriteOnly);
1118 
1119     if (data == nullptr)
1120     {
1121         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock BRC History Buffer.");
1122         eStatus = MOS_STATUS_UNKNOWN;
1123         return eStatus;
1124     }
1125 
1126     MOS_ZeroMemory(data, size);
1127     m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcHistoryBuffer);
1128 
1129     // BRC Intra Distortion Surface
1130     uint32_t width = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x << 3), 64);
1131     uint32_t height = MOS_ALIGN_CEIL((m_downscaledHeightInMb4x << 2), 8) << 1;
1132     allocParamsForBuffer2D.dwWidth = width;
1133     allocParamsForBuffer2D.dwHeight = height;
1134     allocParamsForBuffer2D.pBufName = "BRC Distortion Surface Buffer";
1135 
1136     CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
1137                                                   m_osInterface,
1138                                                   &allocParamsForBuffer2D,
1139                                                   &m_brcBuffers.sBrcIntraDistortionBuffer.OsResource),
1140         "Failed to allocate  ME BRC Distortion Buffer.");
1141 
1142     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, &m_brcBuffers.sBrcIntraDistortionBuffer));
1143     m_brcBuffers.sBrcIntraDistortionBuffer.bArraySpacing = true;
1144     size                                                 = m_brcBuffers.sBrcIntraDistortionBuffer.dwHeight * m_brcBuffers.sBrcIntraDistortionBuffer.dwPitch;
1145 
1146     CODECHAL_ENCODE_CHK_NULL_RETURN(data = (uint8_t *)m_osInterface->pfnLockResource(
1147                                         m_osInterface,
1148                                         &m_brcBuffers.sBrcIntraDistortionBuffer.OsResource,
1149                                         &lockFlagsWriteOnly));
1150 
1151     MOS_ZeroMemory(data, size);
1152     m_osInterface->pfnUnlockResource(
1153         m_osInterface, &m_brcBuffers.sBrcIntraDistortionBuffer.OsResource);
1154 
1155     // PAK Statistics buffer
1156     size                                = m_hevcBrcPakStatisticsSize;
1157     allocParamsForBufferLinear.dwBytes = size;
1158     allocParamsForBufferLinear.pBufName = "BRC PAK Statistics Buffer";
1159 
1160     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1161     {
1162         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1163             m_osInterface,
1164             &allocParamsForBufferLinear,
1165             &m_brcBuffers.resBrcPakStatisticBuffer[i]);
1166 
1167         if (eStatus != MOS_STATUS_SUCCESS)
1168         {
1169             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate BRC PAK Statistics Buffer.");
1170             return eStatus;
1171         }
1172 
1173         data = (uint8_t *)m_osInterface->pfnLockResource(
1174             m_osInterface,
1175             &(m_brcBuffers.resBrcPakStatisticBuffer[i]),
1176             &lockFlagsWriteOnly);
1177 
1178         if (data == nullptr)
1179         {
1180             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock BRC PAK Statistics Buffer.");
1181             eStatus = MOS_STATUS_UNKNOWN;
1182             return eStatus;
1183         }
1184 
1185         MOS_ZeroMemory(data, size);
1186         m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcPakStatisticBuffer[i]);
1187     }
1188 
1189     // PAK HCP_PICTURE_STATEs buffer
1190     size                                = m_brcBuffers.dwBrcHcpPicStateSize;
1191     allocParamsForBufferLinear.dwBytes = size;
1192     allocParamsForBufferLinear.pBufName = "PAK HCP PICTURE State Read Buffer";
1193 
1194     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1195     {
1196         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1197             m_osInterface,
1198             &allocParamsForBufferLinear,
1199             &m_brcBuffers.resBrcImageStatesReadBuffer[i]);
1200 
1201         if (eStatus != MOS_STATUS_SUCCESS)
1202         {
1203             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate HCP PICTURE State Read Buffer.");
1204             return eStatus;
1205         }
1206 
1207         data = (uint8_t *)m_osInterface->pfnLockResource(
1208             m_osInterface,
1209             &(m_brcBuffers.resBrcImageStatesReadBuffer[i]),
1210             &lockFlagsWriteOnly);
1211 
1212         if (data == nullptr)
1213         {
1214             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock HCP PICTURE State Read Buffer.");
1215             eStatus = MOS_STATUS_UNKNOWN;
1216             return eStatus;
1217         }
1218 
1219         MOS_ZeroMemory(data, size);
1220         m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcImageStatesReadBuffer[i]);
1221     }
1222 
1223     allocParamsForBufferLinear.pBufName = "PAK HCP PICTURE State Write Buffer";
1224     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1225     {
1226         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1227             m_osInterface,
1228             &allocParamsForBufferLinear,
1229             &m_brcBuffers.resBrcImageStatesWriteBuffer[i]);
1230 
1231         CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(eStatus, "Failed to allocate HCP PICTURE State Write Buffer.");
1232 
1233         data = (uint8_t *)m_osInterface->pfnLockResource(
1234             m_osInterface,
1235             &m_brcBuffers.resBrcImageStatesWriteBuffer[i],
1236             &lockFlagsWriteOnly);
1237 
1238         if (data == nullptr)
1239         {
1240             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock HCP PICTURE State Write Buffer.");
1241             eStatus = MOS_STATUS_NULL_POINTER;
1242             return eStatus;
1243         }
1244 
1245         MOS_ZeroMemory(data, size);
1246         m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcImageStatesWriteBuffer[i]);
1247     }
1248 
1249     // BRC constant data surface
1250     allocParamsForBuffer2D.dwWidth  = MOS_ALIGN_CEIL(m_brcBuffers.dwBrcConstantSurfaceWidth, 64);
1251     allocParamsForBuffer2D.dwHeight = m_brcBuffers.dwBrcConstantSurfaceHeight;
1252     allocParamsForBuffer2D.pBufName = "BRC Constant Data Buffer";
1253 
1254     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1255     {
1256         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1257             m_osInterface,
1258             &allocParamsForBuffer2D,
1259             &m_brcBuffers.sBrcConstantDataBuffer[i].OsResource);
1260 
1261         if (eStatus != MOS_STATUS_SUCCESS)
1262         {
1263             CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate BRC Constant Data Buffer.");
1264             return eStatus;
1265         }
1266 
1267         CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, &m_brcBuffers.sBrcConstantDataBuffer[i]));
1268         m_brcBuffers.sBrcConstantDataBuffer[i].bArraySpacing = true;
1269     }
1270 
1271     // Use the Mb QP buffer in BrcBuffer for LCU-based Qp surface in HEVC
1272     MOS_ZeroMemory(&m_brcBuffers.sBrcMbQpBuffer, sizeof(m_brcBuffers.sBrcMbQpBuffer));
1273 
1274     // original picture size in MB units aligned to 64 bytes along width and 8 bytes along height
1275     width = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * SCALE_FACTOR_4x), 64);
1276     height = MOS_ALIGN_CEIL((m_downscaledHeightInMb4x * SCALE_FACTOR_4x), 8);
1277     size = width * height;
1278 
1279     allocParamsForBuffer2D.dwWidth = width;
1280     allocParamsForBuffer2D.dwHeight = height;
1281     allocParamsForBuffer2D.pBufName = "BRC MB QP Buffer";
1282 
1283     eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
1284         m_osInterface,
1285         &allocParamsForBuffer2D,
1286         &m_brcBuffers.sBrcMbQpBuffer.OsResource);
1287 
1288     if (eStatus != MOS_STATUS_SUCCESS)
1289     {
1290         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate BRC MB QP Buffer.");
1291         return eStatus;
1292     }
1293 
1294     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, &m_brcBuffers.sBrcMbQpBuffer));
1295     m_brcBuffers.sBrcMbQpBuffer.bArraySpacing = true;
1296 
1297     data = (uint8_t *)m_osInterface->pfnLockResource(
1298         m_osInterface,
1299         &(m_brcBuffers.sBrcMbQpBuffer.OsResource),
1300         &lockFlagsWriteOnly);
1301 
1302     if (data == nullptr)
1303     {
1304         CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock BRC MB QP Buffer.");
1305         eStatus = MOS_STATUS_UNKNOWN;
1306         return eStatus;
1307     }
1308 
1309     MOS_ZeroMemory(data, size);
1310     m_osInterface->pfnUnlockResource(
1311         m_osInterface,
1312         &m_brcBuffers.sBrcMbQpBuffer.OsResource);
1313 
1314     // ROI surface
1315     MOS_ZeroMemory(&m_brcBuffers.sBrcRoiSurface, sizeof(m_brcBuffers.sBrcRoiSurface));
1316 
1317     // original picture size in MB units aligned to 64 bytes along width and 8 bytes along height
1318     // ROI buffer size uses MB units for HEVC, not LCU
1319     width = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x << 4), 64);
1320     height = MOS_ALIGN_CEIL((m_downscaledHeightInMb4x << 2), 8);
1321 
1322     MOS_ZeroMemory(&m_brcBuffers.sBrcRoiSurface, sizeof(m_brcBuffers.sBrcRoiSurface));
1323     m_brcBuffers.sBrcRoiSurface.TileType       = MOS_TILE_LINEAR;
1324     m_brcBuffers.sBrcRoiSurface.bArraySpacing  = true;
1325     m_brcBuffers.sBrcRoiSurface.Format         = Format_Buffer_2D;
1326     m_brcBuffers.sBrcRoiSurface.dwWidth        = width;
1327     m_brcBuffers.sBrcRoiSurface.dwPitch        = width;
1328     m_brcBuffers.sBrcRoiSurface.dwHeight       = height;
1329 
1330     CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D(
1331         &m_brcBuffers.sBrcRoiSurface,
1332         width,
1333         height,
1334         "ROI Buffer"));
1335 
1336     return eStatus;
1337 }
1338 
FreeBrcResources()1339 MOS_STATUS CodechalEncHevcState::FreeBrcResources()
1340 {
1341     CODECHAL_ENCODE_FUNCTION_ENTER;
1342 
1343     m_osInterface->pfnFreeResource(
1344         m_osInterface,
1345         &m_brcBuffers.resBrcHistoryBuffer);
1346 
1347     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
1348     {
1349         m_osInterface->pfnFreeResource(
1350             m_osInterface,
1351             &m_brcBuffers.resBrcPakStatisticBuffer[i]);
1352 
1353         m_osInterface->pfnFreeResource(
1354             m_osInterface,
1355             &m_brcBuffers.resBrcImageStatesReadBuffer[i]);
1356 
1357         m_osInterface->pfnFreeResource(
1358             m_osInterface,
1359             &m_brcBuffers.resBrcImageStatesWriteBuffer[i]);
1360 
1361         m_osInterface->pfnFreeResource(
1362             m_osInterface,
1363             &m_brcBuffers.sBrcConstantDataBuffer[i].OsResource);
1364     }
1365 
1366     m_osInterface->pfnFreeResource(
1367         m_osInterface,
1368         &m_brcBuffers.sBrcIntraDistortionBuffer.OsResource);
1369 
1370     m_osInterface->pfnFreeResource(
1371         m_osInterface,
1372         &m_brcBuffers.sBrcMbQpBuffer.OsResource);
1373 
1374     m_osInterface->pfnFreeResource(
1375         m_osInterface,
1376         &m_brcBuffers.sBrcRoiSurface.OsResource);
1377 
1378     return MOS_STATUS_SUCCESS;
1379 }
1380 
AllocateEncStatsResources()1381 MOS_STATUS CodechalEncHevcState::AllocateEncStatsResources()
1382 {
1383     CODECHAL_ENCODE_FUNCTION_ENTER;
1384 
1385     if (Mos_ResourceIsNull(&m_encStatsBuffers.m_puStatsSurface.OsResource))
1386     {
1387         CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D(
1388             &m_encStatsBuffers.m_puStatsSurface,
1389             m_widthAlignedMaxLcu,
1390             m_heightAlignedMaxLcu >> 5,
1391             "32x32 PU statistics Data Dump surface"));
1392     }
1393 
1394     if (Mos_ResourceIsNull(&m_encStatsBuffers.m_8x8PuHaarDist.OsResource))
1395     {
1396         CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D(
1397             &m_encStatsBuffers.m_8x8PuHaarDist,
1398             m_widthAlignedMaxLcu,
1399             m_heightAlignedMaxLcu >> 4,
1400             "8x8 PU Haar distortion for 16x16 surface"));
1401     }
1402 
1403     if (Mos_ResourceIsNull(&m_encStatsBuffers.m_8x8PuFrameStats.sResource))
1404     {
1405         CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer(
1406                     &m_encStatsBuffers.m_8x8PuFrameStats,
1407                     m_8x8PuFrameStatsSize,
1408                     "8x8 PU frame statistics surface"));
1409     }
1410 
1411     if (Mos_ResourceIsNull(&m_encStatsBuffers.m_mbEncStatsSurface.OsResource))
1412     {
1413         CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D(
1414             &m_encStatsBuffers.m_mbEncStatsSurface,
1415             m_widthAlignedMaxLcu,
1416             m_heightAlignedMaxLcu >> 5,
1417             "MB Enc Statistics data dump surface"));
1418     }
1419 
1420     if (Mos_ResourceIsNull(&m_encStatsBuffers.m_mbEncFrameStats.sResource))
1421     {
1422         CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer(
1423                     &m_encStatsBuffers.m_mbEncFrameStats,
1424                     m_mbEncFrameStatsSize,
1425                     "MB Enc frame statistics surface"));
1426     }
1427 
1428     return MOS_STATUS_SUCCESS;
1429 }
1430 
FreeEncStatsResources()1431 MOS_STATUS CodechalEncHevcState::FreeEncStatsResources()
1432 {
1433     CODECHAL_ENCODE_FUNCTION_ENTER;
1434 
1435     m_osInterface->pfnFreeResource(
1436             m_osInterface,
1437             &m_encStatsBuffers.m_puStatsSurface.OsResource);
1438 
1439     m_osInterface->pfnFreeResource(
1440             m_osInterface,
1441             &m_encStatsBuffers.m_8x8PuHaarDist.OsResource);
1442 
1443     m_osInterface->pfnFreeResource(
1444             m_osInterface,
1445             &m_encStatsBuffers.m_8x8PuFrameStats.sResource);
1446 
1447     m_osInterface->pfnFreeResource(
1448             m_osInterface,
1449             &m_encStatsBuffers.m_mbEncStatsSurface.OsResource);
1450 
1451     m_osInterface->pfnFreeResource(
1452             m_osInterface,
1453             &m_encStatsBuffers.m_mbEncFrameStats.sResource);
1454 
1455     return MOS_STATUS_SUCCESS;
1456 }
1457 
CheckSupportedFormat(PMOS_SURFACE surface)1458 bool CodechalEncHevcState::CheckSupportedFormat(PMOS_SURFACE surface)
1459 {
1460     CODECHAL_ENCODE_FUNCTION_ENTER;
1461 
1462     bool isColorFormatSupported = false;
1463 
1464     if (nullptr == surface)
1465     {
1466         CODECHAL_ENCODE_ASSERTMESSAGE("Invalid (nullptr) Pointer.");
1467         return isColorFormatSupported;
1468     }
1469 
1470     switch (surface->Format)
1471     {
1472     case Format_NV12:
1473         isColorFormatSupported = IS_Y_MAJOR_TILE_FORMAT(surface->TileType);
1474         break;
1475     case Format_P010:
1476         isColorFormatSupported = true;
1477     case Format_YUY2:
1478     case Format_YUYV:
1479     case Format_A8R8G8B8:
1480         break;
1481     default:
1482         CODECHAL_ENCODE_ASSERTMESSAGE("Input surface color format = %d not supported!", surface->Format);
1483         break;
1484     }
1485 
1486     return isColorFormatSupported;
1487 }
1488 
Initialize(CodechalSetting * settings)1489 MOS_STATUS CodechalEncHevcState::Initialize(CodechalSetting * settings)
1490 {
1491     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1492 
1493     CODECHAL_ENCODE_FUNCTION_ENTER;
1494 
1495     // common initilization
1496     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeHevcBase::Initialize(settings));
1497 
1498     m_brcBuffers.dwBrcHcpPicStateSize       = BRC_IMG_STATE_SIZE_PER_PASS * CODECHAL_ENCODE_BRC_MAXIMUM_NUM_PASSES;
1499     m_brcBuffers.uiCurrBrcPakStasIdxForRead = 0;
1500     //Reading buffer is with 2 frames late for BRC kernel uses the PAK statstic info of the frame before the previous frame
1501     m_brcBuffers.uiCurrBrcPakStasIdxForWrite =
1502         (m_brcBuffers.uiCurrBrcPakStasIdxForRead + 2) % CODECHAL_ENCODE_RECYCLED_BUFFER_NUM;
1503 
1504     m_widthAlignedLcu32  = MOS_ALIGN_CEIL(m_frameWidth, 32);
1505     m_heightAlignedLcu32 = MOS_ALIGN_CEIL(m_frameHeight, 32);
1506 
1507     m_hucCommandsSize = m_hwInterface->m_hucCommandBufferSize * CODECHAL_HEVC_MAX_NUM_BRC_PASSES;
1508 
1509     return eStatus;
1510 }
1511 
GetFrameBrcLevel()1512 MOS_STATUS CodechalEncHevcState::GetFrameBrcLevel()
1513 {
1514     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1515 
1516     CODECHAL_ENCODE_FUNCTION_ENTER;
1517 
1518     if (m_lowDelay)
1519     {
1520         // LDB
1521         if (m_pictureCodingType == I_TYPE)
1522         {
1523             if (m_hevcSeqParams->HierarchicalFlag > 0 || m_hevcPicParams->HierarchLevelPlus1 == 0)
1524             {
1525                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_I;
1526             }
1527             else
1528             {
1529                 CODECHAL_ENCODE_ASSERTMESSAGE("FrameLevel can only be 0 for I type for LDB\n");
1530                 return MOS_STATUS_INVALID_PARAMETER;
1531             }
1532         }
1533         else if ((m_pictureCodingType == P_TYPE) || (m_pictureCodingType == B_TYPE))
1534         {
1535             if (m_hevcPicParams->HierarchLevelPlus1 == 0)
1536             {
1537                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_P_OR_LB;
1538             }
1539             else if (m_hevcPicParams->HierarchLevelPlus1 == 1)
1540             {
1541                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_B;
1542             }
1543             else if (m_hevcPicParams->HierarchLevelPlus1 == 2)
1544             {
1545                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_B1;
1546             }
1547             else if (m_hevcPicParams->HierarchLevelPlus1 == 3)
1548             {
1549                 CODECHAL_ENCODE_ASSERTMESSAGE("FrameLevel 3 is not supported for LDB\n");
1550                 return MOS_STATUS_INVALID_PARAMETER;
1551             }
1552             else
1553             {
1554                 CODECHAL_ENCODE_ASSERT(false);
1555                 return MOS_STATUS_INVALID_PARAMETER;
1556             }
1557         }
1558         else if ((m_pictureCodingType == B1_TYPE) || (m_pictureCodingType == B2_TYPE))
1559         {
1560             CODECHAL_ENCODE_ASSERTMESSAGE("B1 & B2 Type is not supported for LDB\n");
1561             return MOS_STATUS_INVALID_PARAMETER;
1562         }
1563         else
1564         {
1565             CODECHAL_ENCODE_ASSERT(false);
1566             return MOS_STATUS_INVALID_PARAMETER;
1567         }
1568     }
1569     else
1570     {
1571         // HB
1572         if (m_pictureCodingType == I_TYPE)
1573         {
1574                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_I;
1575         }
1576         else if (m_pictureCodingType == B_TYPE)
1577         {
1578                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_B;
1579         }
1580         else if (m_pictureCodingType == B1_TYPE)
1581         {
1582                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_B1;
1583         }
1584         else if (m_pictureCodingType == B2_TYPE)
1585         {
1586                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_B2;
1587         }
1588         else if (m_pictureCodingType == P_TYPE)
1589         {
1590                 m_currFrameBrcLevel = HEVC_BRC_FRAME_TYPE_P_OR_LB;
1591         }
1592         else
1593         {
1594                 CODECHAL_ENCODE_ASSERT(false);
1595                 return MOS_STATUS_INVALID_PARAMETER;
1596         }
1597     }
1598 
1599     return eStatus;
1600 }
1601 
InitializePicture(const EncoderParams & params)1602 MOS_STATUS CodechalEncHevcState::InitializePicture(const EncoderParams& params)
1603 {
1604     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1605 
1606     CODECHAL_ENCODE_FUNCTION_ENTER;
1607 
1608     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeHevcBase::InitializePicture(params));
1609     CODECHAL_ENCODE_CHK_STATUS_RETURN(GetFrameBrcLevel());
1610 
1611     return eStatus;
1612 }
1613 
SetMeCurbeParams(CodechalKernelHme::CurbeParam & curbeParams)1614 MOS_STATUS CodechalEncHevcState::SetMeCurbeParams(
1615     CodechalKernelHme::CurbeParam &curbeParams)
1616 {
1617     CODECHAL_ENCODE_FUNCTION_ENTER;
1618 
1619     // Setup ME Params
1620     MOS_ZeroMemory(&curbeParams, sizeof(curbeParams));
1621     curbeParams.subPelMode        = 3;
1622     curbeParams.currOriginalPic   = m_hevcPicParams->CurrOriginalPic;
1623     curbeParams.qpPrimeY          = m_hevcPicParams->QpY + m_hevcSliceParams->slice_qp_delta;
1624     curbeParams.targetUsage       = m_hevcSeqParams->TargetUsage;
1625     curbeParams.maxMvLen          = CODECHAL_ENCODE_HEVC_MAX_MV_LEN_AVC_LEVEL_51;
1626     curbeParams.numRefIdxL0Minus1 = m_hevcSliceParams->num_ref_idx_l0_active_minus1;
1627     curbeParams.numRefIdxL1Minus1 = m_hevcSliceParams->num_ref_idx_l1_active_minus1;
1628     curbeParams.bmeMethodTable    = m_bmeMethodTable;
1629     curbeParams.meMethodTable     = m_meMethodTable;
1630 
1631     return MOS_STATUS_SUCCESS;
1632 }
1633 
SetMeSurfaceParams(CodechalKernelHme::SurfaceParams & surfaceParams)1634 MOS_STATUS CodechalEncHevcState::SetMeSurfaceParams(
1635     CodechalKernelHme::SurfaceParams     &surfaceParams)
1636 {
1637     CODECHAL_ENCODE_FUNCTION_ENTER;
1638 
1639     // Setup ME Params
1640     MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams));
1641     surfaceParams.mbaffEnabled                     = false;
1642     surfaceParams.numRefIdxL0ActiveMinus1          = m_hevcSliceParams->num_ref_idx_l0_active_minus1;
1643     surfaceParams.numRefIdxL1ActiveMinus1          = m_hevcSliceParams->num_ref_idx_l1_active_minus1;
1644     surfaceParams.verticalLineStride               = m_verticalLineStride;
1645     surfaceParams.verticalLineStrideOffset         = m_verticalLineStrideOffset;
1646     surfaceParams.meBrcDistortionBuffer            = &m_brcBuffers.sMeBrcDistortionBuffer;
1647     surfaceParams.meBrcDistortionBottomFieldOffset = m_brcBuffers.dwMeBrcDistortionBottomFieldOffset;
1648     surfaceParams.refList                          = &m_refList[0];
1649     surfaceParams.picIdx                           = &m_picIdx[0];
1650     surfaceParams.currOriginalPic                  = &m_currOriginalPic;
1651     surfaceParams.refL0List                        = &(m_hevcSliceParams->RefPicList[LIST_0][0]);
1652     surfaceParams.refL1List                        = &(m_hevcSliceParams->RefPicList[LIST_1][0]);
1653 
1654     return MOS_STATUS_SUCCESS;
1655 }
1656 
EncodeMeKernel()1657 MOS_STATUS CodechalEncHevcState::EncodeMeKernel()
1658 {
1659     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1660 
1661     CODECHAL_ENCODE_FUNCTION_ENTER;
1662 
1663     // Walker must be used for HME call and scaling one
1664     CODECHAL_ENCODE_ASSERT(m_hwWalker);
1665 
1666     if (m_hmeKernel && m_hmeKernel->Is4xMeEnabled())
1667     {
1668         CodechalKernelHme::CurbeParam curbeParam;
1669         CODECHAL_ENCODE_CHK_STATUS_RETURN(SetMeCurbeParams(curbeParam));
1670 
1671         CodechalKernelHme::SurfaceParams surfaceParam;
1672         CODECHAL_ENCODE_CHK_STATUS_RETURN(SetMeSurfaceParams(surfaceParam));
1673         if (m_hmeKernel->Is16xMeEnabled())
1674         {
1675             if (m_hmeKernel->Is32xMeEnabled())
1676             {
1677                 surfaceParam.downScaledWidthInMb         = m_downscaledWidthInMb32x;
1678                 surfaceParam.downScaledHeightInMb        = m_downscaledFrameFieldHeightInMb32x;
1679                 surfaceParam.downScaledBottomFieldOffset = m_scaled32xBottomFieldOffset;
1680                 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hmeKernel->Execute(curbeParam, surfaceParam, CodechalKernelHme::HmeLevel::hmeLevel32x));
1681             }
1682             surfaceParam.downScaledWidthInMb         = m_downscaledWidthInMb16x;
1683             surfaceParam.downScaledHeightInMb        = m_downscaledFrameFieldHeightInMb16x;
1684             surfaceParam.downScaledBottomFieldOffset = m_scaled16xBottomFieldOffset;
1685             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hmeKernel->Execute(curbeParam, surfaceParam, CodechalKernelHme::HmeLevel::hmeLevel16x));
1686         }
1687         surfaceParam.downScaledWidthInMb         = m_downscaledWidthInMb4x;
1688         surfaceParam.downScaledHeightInMb        = m_downscaledFrameFieldHeightInMb4x;
1689         surfaceParam.downScaledBottomFieldOffset = m_scaledBottomFieldOffset;
1690         m_lastTaskInPhase = true;
1691 
1692         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hmeKernel->Execute(curbeParam, surfaceParam, CodechalKernelHme::HmeLevel::hmeLevel4x));
1693     }
1694 
1695     CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpHMESurfaces());
1696 
1697     return eStatus;
1698 }
1699 
DumpHMESurfaces()1700 MOS_STATUS CodechalEncHevcState::DumpHMESurfaces()
1701 {
1702     CODECHAL_ENCODE_FUNCTION_ENTER;
1703 
1704     CODECHAL_DEBUG_TOOL(
1705     if (m_hmeEnabled) {
1706         PMOS_SURFACE dumpBuffer = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me4xMvDataBuffer);
1707         if (dumpBuffer)
1708         {
1709             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
1710                 &dumpBuffer->OsResource,
1711                 CodechalDbgAttr::attrOutput,
1712                 "MvData",
1713                 dumpBuffer->dwHeight *dumpBuffer->dwPitch,
1714                 CodecHal_PictureIsBottomField(m_currOriginalPic) ? MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64) * (m_downscaledFrameFieldHeightInMb4x * 4) : 0,
1715                 CODECHAL_MEDIA_STATE_4X_ME));
1716         }
1717 
1718         dumpBuffer = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me4xDistortionBuffer);
1719         if (dumpBuffer)
1720         {
1721             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
1722                 &dumpBuffer->OsResource,
1723                 CodechalDbgAttr::attrOutput,
1724                 "MeDist",
1725                 dumpBuffer->dwHeight * dumpBuffer->dwPitch,
1726                 CodecHal_PictureIsBottomField(m_currOriginalPic) ? MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64) * MOS_ALIGN_CEIL((m_downscaledFrameFieldHeightInMb4x * 4), 8) : 0,
1727                 CODECHAL_MEDIA_STATE_4X_ME));
1728         }
1729 
1730         if (m_b16XMeEnabled)
1731         {
1732             dumpBuffer = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me16xMvDataBuffer);
1733             //    &meOutputParams));
1734 
1735             CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
1736                 &dumpBuffer->OsResource,
1737                 CodechalDbgAttr::attrOutput,
1738                 "MvData",
1739                 dumpBuffer->dwHeight *dumpBuffer->dwPitch,
1740                 CodecHal_PictureIsBottomField(m_currOriginalPic) ? MOS_ALIGN_CEIL((m_downscaledWidthInMb16x * 32), 64) * (m_downscaledFrameFieldHeightInMb16x * 4) : 0,
1741                 CODECHAL_MEDIA_STATE_16X_ME));
1742 
1743             if (m_b32XMeEnabled)
1744             {
1745                 dumpBuffer = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me32xMvDataBuffer);
1746                 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
1747                     &dumpBuffer->OsResource,
1748                     CodechalDbgAttr::attrOutput,
1749                     "MvData",
1750                     dumpBuffer->dwHeight *dumpBuffer->dwPitch,
1751                     CodecHal_PictureIsBottomField(m_currOriginalPic) ? MOS_ALIGN_CEIL((m_downscaledWidthInMb32x * 32), 64) * (m_downscaledFrameFieldHeightInMb32x * 4) : 0,
1752                     CODECHAL_MEDIA_STATE_32X_ME));
1753             }
1754         }
1755     })
1756 
1757     return MOS_STATUS_SUCCESS;
1758 }
1759 
SetupROISurface()1760 MOS_STATUS CodechalEncHevcState::SetupROISurface()
1761 {
1762     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1763 
1764     CODECHAL_ENCODE_FUNCTION_ENTER;
1765 
1766     MOS_LOCK_PARAMS ReadOnly;
1767     MOS_ZeroMemory(&ReadOnly, sizeof(ReadOnly));
1768     ReadOnly.ReadOnly = 1;
1769     uint32_t * dataPtr = (uint32_t *)m_osInterface->pfnLockResource(m_osInterface, &m_brcBuffers.sBrcRoiSurface.OsResource, &ReadOnly);
1770     if (!dataPtr)
1771     {
1772         eStatus = MOS_STATUS_INVALID_HANDLE;
1773         return eStatus;
1774     }
1775 
1776     uint32_t bufferWidthInByte  = m_brcBuffers.sBrcRoiSurface.dwPitch;
1777     uint32_t bufferHeightInByte = MOS_ALIGN_CEIL((m_downscaledHeightInMb4x << 2), 8);
1778     uint32_t numMBs = m_picWidthInMb * m_picHeightInMb;
1779     for (uint32_t uMB = 0; uMB <= numMBs; uMB++)
1780     {
1781         int32_t curMbY = uMB / m_picWidthInMb;
1782         int32_t curMbX = uMB - curMbY * m_picWidthInMb;
1783 
1784         uint32_t outdata = 0;
1785         for (int32_t roiIdx = (m_hevcPicParams->NumROI - 1); roiIdx >= 0; roiIdx--)
1786         {
1787             int32_t qpLevel;
1788             if (m_roiValueInDeltaQp)
1789             {
1790                 qpLevel = m_hevcPicParams->ROI[roiIdx].PriorityLevelOrDQp;
1791             }
1792             else
1793             {
1794                 // QP Level sent to ROI surface is (priority * 5)
1795                 //qpLevel = m_hevcPicParams->ROI[roiIdx].PriorityLevelOrDQp * 6;
1796                 CODECHAL_ENCODE_ASSERTMESSAGE("error: ROI does not support priority level for now.");
1797                 return MOS_STATUS_INVALID_PARAMETER;
1798             }
1799 
1800             if (qpLevel == 0)
1801             {
1802                 continue;
1803             }
1804 
1805             if ((curMbX >= (int32_t)m_hevcPicParams->ROI[roiIdx].Left) && (curMbX < (int32_t)m_hevcPicParams->ROI[roiIdx].Right) &&
1806                 (curMbY >= (int32_t)m_hevcPicParams->ROI[roiIdx].Top) && (curMbY < (int32_t)m_hevcPicParams->ROI[roiIdx].Bottom))
1807             {
1808                 outdata = 15 | ((qpLevel & 0xFF) << 16);
1809             }
1810             else if (m_roiRegionSmoothEnabled)
1811             {
1812                 if ((curMbX >= (int32_t)m_hevcPicParams->ROI[roiIdx].Left - 1) && (curMbX < (int32_t)m_hevcPicParams->ROI[roiIdx].Right + 1) &&
1813                     (curMbY >= (int32_t)m_hevcPicParams->ROI[roiIdx].Top - 1) && (curMbY < (int32_t)m_hevcPicParams->ROI[roiIdx].Bottom + 1))
1814                 {
1815                     outdata = 14 | ((qpLevel & 0xFF) << 16);
1816                 }
1817                 else if ((curMbX >= (int32_t)m_hevcPicParams->ROI[roiIdx].Left - 2) && (curMbX < (int32_t)m_hevcPicParams->ROI[roiIdx].Right + 2) &&
1818                          (curMbY >= (int32_t)m_hevcPicParams->ROI[roiIdx].Top - 2) && (curMbY < (int32_t)m_hevcPicParams->ROI[roiIdx].Bottom + 2))
1819                 {
1820                     outdata = 13 | ((qpLevel & 0xFF) << 16);
1821                 }
1822                 else if ((curMbX >= (int32_t)m_hevcPicParams->ROI[roiIdx].Left - 3) && (curMbX < (int32_t)m_hevcPicParams->ROI[roiIdx].Right + 3) &&
1823                          (curMbY >= (int32_t)m_hevcPicParams->ROI[roiIdx].Top - 3) && (curMbY < (int32_t)m_hevcPicParams->ROI[roiIdx].Bottom + 3))
1824                 {
1825                     outdata = 12 | ((qpLevel & 0xFF) << 16);
1826                 }
1827             }
1828         }
1829         dataPtr[(curMbY * (bufferWidthInByte >> 2)) + curMbX] = outdata;
1830     }
1831 
1832     m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.sBrcRoiSurface.OsResource);
1833 
1834     uint32_t bufferSize = bufferWidthInByte * bufferHeightInByte;
1835     CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
1836         &m_brcBuffers.sBrcRoiSurface.OsResource,
1837         CodechalDbgAttr::attrROISurface,
1838         "ROIInputSurface",
1839         bufferSize,
1840         0,
1841         CODECHAL_NUM_MEDIA_STATES)));
1842 
1843     return eStatus;
1844 }
1845 
GetRoundingIntraInterToUse()1846 MOS_STATUS CodechalEncHevcState::GetRoundingIntraInterToUse()
1847 {
1848     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1849 
1850     CODECHAL_ENCODE_FUNCTION_ENTER;
1851 
1852     if (m_hevcPicParams->CustomRoundingOffsetsParams.fields.EnableCustomRoudingIntra)
1853     {
1854         m_roundingIntraInUse = m_hevcPicParams->CustomRoundingOffsetsParams.fields.RoundingOffsetIntra;
1855     }
1856     else
1857     {
1858         if (m_hevcSeqParams->NumOfBInGop[1] != 0 || m_hevcSeqParams->NumOfBInGop[2] != 0)
1859         {
1860             //Hierachical B GOP
1861             if (m_hevcPicParams->CodingType == I_TYPE ||
1862                 m_hevcPicParams->CodingType == P_TYPE)
1863             {
1864                 m_roundingIntraInUse = 4;
1865             }
1866             else if (m_hevcPicParams->CodingType == B_TYPE)
1867             {
1868                 m_roundingIntraInUse = 3;
1869             }
1870             else
1871             {
1872                 m_roundingIntraInUse = 2;
1873             }
1874         }
1875         else
1876         {
1877             m_roundingIntraInUse = 10;
1878         }
1879     }
1880 
1881     if (m_hevcPicParams->CustomRoundingOffsetsParams.fields.EnableCustomRoudingInter)
1882     {
1883         m_roundingInterInUse = m_hevcPicParams->CustomRoundingOffsetsParams.fields.RoundingOffsetInter;
1884     }
1885     else
1886     {
1887         if (m_hevcSeqParams->NumOfBInGop[1] != 0 || m_hevcSeqParams->NumOfBInGop[2] != 0)
1888         {
1889             //Hierachical B GOP
1890             if (m_hevcPicParams->CodingType == I_TYPE ||
1891                 m_hevcPicParams->CodingType == P_TYPE)
1892             {
1893                 m_roundingInterInUse = 4;
1894             }
1895             else if (m_hevcPicParams->CodingType == B_TYPE)
1896             {
1897                 m_roundingInterInUse = 3;
1898             }
1899             else
1900             {
1901                 m_roundingInterInUse = 2;
1902             }
1903         }
1904         else
1905         {
1906             m_roundingInterInUse = 4;
1907         }
1908     }
1909 
1910     return eStatus;
1911 }
1912 
1913