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