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, ¶ms));
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