1 /*
2 * Copyright (c) 2019-2022, 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     encode_av1_segmentation.cpp
24 //! \brief    Defines the common interface for encode av1 segmentation feature
25 //!
26 
27 #include "encode_av1_segmentation.h"
28 #include "encode_av1_basic_feature.h"
29 #include "encode_av1_stream_in.h"
30 
31 namespace encode
32 {
Av1Segmentation(MediaFeatureManager * featureManager,EncodeAllocator * allocator,void * constSettings)33     Av1Segmentation::Av1Segmentation(
34         MediaFeatureManager *featureManager,
35         EncodeAllocator *allocator,
36         void *constSettings) :
37         MediaFeature(constSettings),
38         m_allocator(allocator)
39     {
40         ENCODE_FUNC_CALL();
41         ENCODE_CHK_NULL_NO_STATUS_RETURN(featureManager);
42 
43         m_basicFeature = dynamic_cast<Av1BasicFeature *>(featureManager->GetFeature(Av1FeatureIDs::basicFeature));
44         m_featureManager = featureManager;
45         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
46     }
47 
~Av1Segmentation()48     Av1Segmentation::~Av1Segmentation()
49     {
50         ENCODE_FUNC_CALL();
51     }
52 
GetBlockSize(uint32_t blockSizeId)53     inline uint8_t GetBlockSize(uint32_t blockSizeId)
54     {
55         switch (blockSizeId)
56         {
57         case 0: return 16;
58         case 1: return 32;
59         case 2: return 64;
60         case 3: return 8;
61         default:
62             ENCODE_ASSERTMESSAGE("Block size for segment map must be set");
63             return 16;
64         }
65     }
66 
Update(void * params)67     MOS_STATUS Av1Segmentation::Update(void *params)
68     {
69         ENCODE_FUNC_CALL();
70         ENCODE_CHK_NULL_RETURN(params);
71 
72         EncoderParamsAV1 *encodeParams = (EncoderParamsAV1 *)params;
73 
74         const auto av1PicParams = static_cast<PCODEC_AV1_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
75         ENCODE_CHK_NULL_RETURN(av1PicParams);
76 
77         const auto av1SeqParams = static_cast<PCODEC_AV1_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams);
78         ENCODE_CHK_NULL_RETURN(av1SeqParams);
79 
80         m_targetUsage = av1SeqParams->TargetUsage;
81 
82         const auto& ddiSegments = av1PicParams->stAV1Segments;
83 
84         MOS_ZeroMemory(&m_segmentParams, sizeof(m_segmentParams));
85         for (auto i = 0; i < av1MaxSegments; i++)
86         {
87             // set QM related to default value.
88             m_segmentParams.m_qmLevelU[i] = m_segmentParams.m_qmLevelV[i] = m_segmentParams.m_qmLevelY[i] = 15;
89 
90             if (av1PicParams->wQMatrixFlags.fields.using_qmatrix)
91             {
92                 m_segmentParams.m_qmLevelY[i] = av1PicParams->wQMatrixFlags.fields.qm_y;
93                 m_segmentParams.m_qmLevelU[i] = av1PicParams->wQMatrixFlags.fields.qm_u;
94                 m_segmentParams.m_qmLevelV[i] = av1PicParams->wQMatrixFlags.fields.qm_v;
95             }
96         }
97 
98         m_segmentParams.m_enabled = ddiSegments.SegmentFlags.fields.segmentation_enabled;
99         m_segmentParams.m_updateMap = ddiSegments.SegmentFlags.fields.update_map;
100         m_segmentParams.m_temporalUpdate = ddiSegments.SegmentFlags.fields.temporal_update;
101 
102         m_segmentNum = ddiSegments.SegmentFlags.fields.SegmentNumber;
103 
104         m_segmentMapBlockSize = GetBlockSize(av1PicParams->PicFlags.fields.SegIdBlockSize);
105 
106         m_hasZeroSegmentQIndex = false;
107 
108         const auto currRefList = m_basicFeature->m_ref.GetCurrRefList();
109         ENCODE_CHK_NULL_RETURN(currRefList);
110         if (av1PicParams->PicFlags.fields.frame_type == keyFrame)
111         {
112             memset(m_segmenBufferinUse, 0, sizeof(m_segmenBufferinUse));
113             memset(m_ucScalingIdtoSegID, -1, sizeof(m_ucScalingIdtoSegID));
114         }
115         if (!m_basicFeature->m_av1PicParams->PicFlags.fields.DisableFrameRecon &&
116             m_ucScalingIdtoSegID[currRefList->ucScalingIdx] != -1)
117         {
118             m_segmenBufferinUse[m_ucScalingIdtoSegID[currRefList->ucScalingIdx]]--;
119         }
120 
121         if (m_segmentParams.m_enabled)
122         {
123             ENCODE_CHK_STATUS_RETURN(SetSegmentIdParams(av1PicParams, &ddiSegments));
124 
125             m_pSegmentMap = nullptr;
126             m_segmentMapProvided = false;
127             m_segmentMapDataSize = 0;
128 
129             if (encodeParams->pSegmentMap)
130             {
131                 m_pSegmentMap = encodeParams->pSegmentMap;
132                 m_segmentMapProvided = encodeParams->bSegmentMapProvided;
133                 m_segmentMapDataSize = encodeParams->segmentMapDataSize;
134             }
135 
136             if (m_segmentParams.m_temporalUpdate != 0)
137             {
138                 if (!m_segmentParams.m_updateMap)
139                 {
140                     ENCODE_ASSERTMESSAGE("\"Temporal_update\" is set when \"update_map\" is zero");
141                     return MOS_STATUS_INVALID_PARAMETER;
142                 }
143 
144                 const auto primRefList = m_basicFeature->m_ref.GetPrimaryRefList();
145                 ENCODE_CHK_NULL_RETURN(primRefList);
146 
147                 const uint8_t ft = av1PicParams->PicFlags.fields.frame_type;
148                 if (ft == keyFrame || ft == intraOnlyFrame || !primRefList->m_segmentEnable)
149                 {
150                     ENCODE_ASSERTMESSAGE("Temporal update for segmentation map cannot be applied");
151                     return MOS_STATUS_INVALID_PARAMETER;
152                 }
153             }
154 
155             ENCODE_CHK_STATUS_RETURN(CheckQPAndLossless());
156 
157             if (m_segmentMapProvided)
158             {
159                 m_streamIn = m_basicFeature->GetStreamIn();
160                 ENCODE_CHK_NULL_RETURN(m_streamIn);
161                 ENCODE_CHK_STATUS_RETURN(m_streamIn->Update());
162                 ENCODE_CHK_STATUS_RETURN(SetupSegmentationMap());
163             }
164         }
165         else
166         {
167             if (m_segmentParams.m_updateData || m_segmentParams.m_temporalUpdate)
168             {
169                 ENCODE_ASSERTMESSAGE("\"Update_map\" or \"temporal_update\" is enabled when segmentation is disabled.");
170                 return MOS_STATUS_INVALID_PARAMETER;
171             }
172 
173             // even if segmentation is disabled, segment params for segment 0 are still passed to HW
174             // lossless flag should be set correctly for segment 0
175             m_segmentParams.m_losslessFlag[0] = IsFrameLossless(*av1PicParams);
176 
177             m_hasZeroSegmentQIndex = av1PicParams->base_qindex == 0;
178         }
179 
180         return MOS_STATUS_SUCCESS;
181     }
182 
CheckQPAndLossless()183     MOS_STATUS Av1Segmentation::CheckQPAndLossless()
184     {
185         ENCODE_FUNC_CALL();
186 
187         const auto* picPar = m_basicFeature->m_av1PicParams;
188 
189         ENCODE_CHK_NULL_RETURN(picPar);
190 
191         if (IsFrameLossless(*picPar))
192         {
193             ENCODE_ASSERTMESSAGE("Segmentation can't be enabled for lossless frame.");
194             return MOS_STATUS_INVALID_PARAMETER;
195         }
196 
197         for (uint8_t i = 0; i < m_segmentNum; i++)
198         {
199             const int16_t segQP = picPar->base_qindex + m_segmentParams.m_featureData[i][segLvlAltQ];
200 
201             if (segQP < 0)
202             {
203                 ENCODE_ASSERTMESSAGE("segQP < 0 is not supported.");
204                 return MOS_STATUS_INVALID_PARAMETER;
205             }
206 
207             const uint8_t clippedSegQP = static_cast<uint8_t>(CodecHal_Clip3(0, 255, segQP));
208 
209             if (clippedSegQP == 0)
210             {
211                 if (DeltaQIsZero(*picPar))
212                 {
213                     ENCODE_ASSERTMESSAGE("Lossless segment isn't supported.");
214                     return MOS_STATUS_INVALID_PARAMETER;
215                 }
216 
217                 m_hasZeroSegmentQIndex = true;
218             }
219 
220             m_segmentParams.m_featureData[i][segLvlAltQ] = clippedSegQP - picPar->base_qindex;
221         }
222 
223         return MOS_STATUS_SUCCESS;
224     }
225 
SetSegmentIdParams(const PCODEC_AV1_ENCODE_PICTURE_PARAMS ddiPicParams,const CODEC_Intel_Seg_AV1 * ddiSegParams)226     MOS_STATUS Av1Segmentation::SetSegmentIdParams(
227         const PCODEC_AV1_ENCODE_PICTURE_PARAMS  ddiPicParams,
228         const CODEC_Intel_Seg_AV1              *ddiSegParams)
229     {
230         ENCODE_FUNC_CALL();
231 
232         ENCODE_CHK_NULL_RETURN(ddiPicParams);
233         ENCODE_CHK_NULL_RETURN(ddiSegParams);
234         ENCODE_CHK_NULL_RETURN(m_basicFeature);
235 
236         for (auto i = 0; i < av1MaxSegments; i++)
237         {
238             if (ddiPicParams->wQMatrixFlags.fields.using_qmatrix)
239             {
240                 m_segmentParams.m_qmLevelU[i] = ddiPicParams->wQMatrixFlags.fields.qm_u;
241                 m_segmentParams.m_qmLevelV[i] = ddiPicParams->wQMatrixFlags.fields.qm_v;
242                 m_segmentParams.m_qmLevelY[i] = ddiPicParams->wQMatrixFlags.fields.qm_y;
243             }
244         }
245 
246         MOS_SecureMemcpy(
247             m_segmentParams.m_featureData,
248             sizeof(m_segmentParams.m_featureData),
249             ddiSegParams->feature_data,
250             sizeof(m_segmentParams.m_featureData));
251 
252         MOS_SecureMemcpy(
253             m_segmentParams.m_featureMask,
254             sizeof(m_segmentParams.m_featureMask),
255             ddiSegParams->feature_mask,
256             sizeof(m_segmentParams.m_featureMask));
257 
258         for (uint8_t seg = 0; seg < av1MaxSegments; seg++)
259         {
260             for (int lvl = 0; lvl < segLvlMax; lvl++)
261             {
262                 if (m_segmentParams.m_featureMask[seg] & (1 << lvl))
263                 {
264                     m_segmentParams.m_preSkipSegmentIdFlag |= (lvl >= segLvlRefFrame);
265                     m_segmentParams.m_lastActiveSegmentId = seg;
266                 }
267             }
268         }
269 
270         // Configure Segment ID read buffer and SegmentMapIsZeroFlag
271         m_segmentParams.m_segmentMapIsZeroFlag = false;
272         // pass AVP seg map stream-in only in case of segmentation_temporal_update = 1
273         m_segmentParams.m_segIdBufStreamInEnable = m_segmentParams.m_temporalUpdate ? true : false;
274         // pass AVP seg map stream-out only if segmentation_update_map = 1
275         m_segmentParams.m_segIdBufStreamOutEnable = m_segmentParams.m_updateMap ? true : false;
276 
277         const bool usePrimaryMap = !m_segmentParams.m_updateMap || m_segmentParams.m_temporalUpdate;
278 
279         if (usePrimaryMap)
280         {
281             if (!m_basicFeature->m_ref.CheckSegmentForPrimeFrame())
282             {
283                 m_segmentParams.m_segmentMapIsZeroFlag   = true;
284                 m_segmentParams.m_segIdBufStreamInEnable = false;
285             }
286         }
287 
288         if (!m_basicFeature->m_av1PicParams->PicFlags.fields.DisableFrameRecon)
289         {
290             const auto currRefList = m_basicFeature->m_ref.GetCurrRefList();
291             ENCODE_CHK_NULL_RETURN(currRefList);
292             if (!m_segmentParams.m_segIdBufStreamOutEnable)
293             {
294                 const auto primRefList = m_basicFeature->m_ref.GetPrimaryRefList();
295                 ENCODE_CHK_NULL_RETURN(primRefList);
296                 currRefList->m_segIdBufIdx = primRefList->m_segIdBufIdx;
297             }
298             else
299             {
300                 //the maximum DPB length of AV1 is 8, free IDs will always be found.
301                 for (uint8_t i = 0; i < av1TotalRefsPerFrame; i++)
302                 {
303                     if (m_segmenBufferinUse[i] == 0)
304                     {
305                         currRefList->m_segIdBufIdx = i;
306                         break;
307                     }
308                 }
309             }
310             if (m_segmentMapBuffer[currRefList->m_segIdBufIdx] == nullptr)
311             {
312                 ENCODE_CHK_STATUS_RETURN(AllocateSegmentationMapBuffer(currRefList->m_segIdBufIdx));
313             }
314             m_segmenBufferinUse[currRefList->m_segIdBufIdx]++;
315             m_ucScalingIdtoSegID[currRefList->ucScalingIdx] = currRefList->m_segIdBufIdx;
316         }
317 
318         return MOS_STATUS_SUCCESS;
319     }
320 
SetupSegmentationMap()321     MOS_STATUS Av1Segmentation::SetupSegmentationMap()
322     {
323         ENCODE_FUNC_CALL();
324 
325         ENCODE_CHK_STATUS_RETURN(CheckSegmentationMap());
326 
327         auto streamInData = m_streamIn->GetStreamInBuffer();
328         ENCODE_CHK_STATUS_RETURN(FillSegmentationMap((VdencStreamInState *)streamInData));
329 
330         ENCODE_CHK_STATUS_RETURN(m_streamIn->ReturnStreamInBuffer());
331 
332         return MOS_STATUS_SUCCESS;
333     }
334 
CheckSegmentationMap() const335     MOS_STATUS Av1Segmentation::CheckSegmentationMap() const
336     {
337         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_av1PicParams);
338 
339         auto CurFrameWidth  = m_basicFeature->m_av1PicParams->frame_width_minus1 + 1;
340         auto CurFrameHeight = m_basicFeature->m_av1PicParams->frame_height_minus1 + 1;
341 
342         const uint32_t segMapPitch  = MOS_ALIGN_CEIL(CurFrameWidth, m_segmentMapBlockSize) / m_segmentMapBlockSize;
343         const uint32_t segMapHeight = MOS_ALIGN_CEIL(CurFrameHeight, m_segmentMapBlockSize) / m_segmentMapBlockSize;
344 
345         const uint64_t minSegmentMapDataSize = (uint64_t)segMapPitch * (uint64_t)segMapHeight;  // 1 byte per segment Id
346 
347         if (m_segmentMapDataSize < minSegmentMapDataSize)
348         {
349             ENCODE_ASSERTMESSAGE("Size of segmentation map data provided by app isn't enough for frame resolution");
350             return MOS_STATUS_INVALID_PARAMETER;
351         }
352 
353         return MOS_STATUS_SUCCESS;
354     }
355 
ScaleCoord(uint32_t coord,uint32_t oldUnit,uint32_t newUnit)356     inline uint32_t ScaleCoord(uint32_t coord, uint32_t oldUnit, uint32_t newUnit)
357     {
358         ENCODE_ASSERT(newUnit);
359         return (coord * oldUnit) / newUnit;
360     }
361 
FillSegmentationMap(VdencStreamInState * streamInData) const362     MOS_STATUS Av1Segmentation::FillSegmentationMap(VdencStreamInState* streamInData) const
363     {
364         ENCODE_FUNC_CALL();
365         ENCODE_CHK_NULL_RETURN(streamInData);
366         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_av1PicParams);
367 
368         const uint8_t blockSize = Av1StreamIn::m_streamInBlockSize;
369         auto CurFrameWidth  = m_basicFeature->m_av1PicParams->frame_width_minus1 + 1;
370         auto CurFrameHeight = m_basicFeature->m_av1PicParams->frame_height_minus1 + 1;
371 
372         uint16_t FrameWidthInStreamInBlocks  = MOS_ALIGN_CEIL(CurFrameWidth, blockSize) / blockSize;
373         uint16_t FrameHeightInStreamInBlocks = MOS_ALIGN_CEIL(CurFrameHeight, blockSize) / blockSize;
374 
375         for (int yIdx = 0; yIdx < FrameHeightInStreamInBlocks; yIdx++)
376         {
377             for (uint32_t xIdx = 0; xIdx < FrameWidthInStreamInBlocks; xIdx++)
378             {
379                 const uint32_t IdxBlockInStreamIn = m_streamIn->GetCuOffset(xIdx, yIdx);
380                 const uint32_t segMapPitch = MOS_ALIGN_CEIL(CurFrameWidth, m_segmentMapBlockSize) / m_segmentMapBlockSize;
381                 const uint32_t segMapY = ScaleCoord(yIdx, blockSize, m_segmentMapBlockSize);
382                 const uint32_t segMapX = ScaleCoord(xIdx, blockSize, m_segmentMapBlockSize);
383 
384                 ENCODE_ASSERT(m_pSegmentMap);
385 
386                 const uint8_t segId = m_pSegmentMap[segMapY * segMapPitch + segMapX];
387 
388                 streamInData[IdxBlockInStreamIn].DW7.SegIDEnable = 1;
389                 // Minimum size for a SegID is a 32x32 block.
390                 // All four 16x16 blocks within a 32x32 should share the same Segmentation ID.
391                 streamInData[IdxBlockInStreamIn].DW7.SegID = segId | (segId << 4) | (segId << 8) | (segId << 12);
392 
393             }
394         }
395         return MOS_STATUS_SUCCESS;
396     }
397 
AllocateSegmentationMapBuffer(uint8_t segmentBufid)398     MOS_STATUS Av1Segmentation::AllocateSegmentationMapBuffer(uint8_t segmentBufid)
399     {
400         if (segmentBufid >= av1TotalRefsPerFrame)
401         {
402             ENCODE_ASSERTMESSAGE("segment map number exceed.");
403             return MOS_STATUS_INVALID_PARAMETER;
404         }
405         if (m_segmentMapBuffer[segmentBufid] != nullptr)
406         {
407             return MOS_STATUS_SUCCESS;
408         }
409 
410         uint32_t       totalSbPerFrame         = (m_basicFeature->m_picWidthInSb) * (m_basicFeature->m_picHeightInSb);
411         const uint16_t num4x4BlocksIn64x64Sb   = 256;
412         const uint16_t num4x4BlocksIn128x128Sb = 1024;
413         const uint32_t sizeOfSegmentIdMap      = ((m_basicFeature->m_isSb128x128) ? num4x4BlocksIn128x128Sb : num4x4BlocksIn64x64Sb) * totalSbPerFrame;
414 
415         MOS_ALLOC_GFXRES_PARAMS allocParams;
416         MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));
417         allocParams.Type               = MOS_GFXRES_BUFFER;
418         allocParams.TileType           = MOS_TILE_LINEAR;
419         allocParams.Format             = Format_Buffer;
420         allocParams.Flags.bNotLockable = false;
421         allocParams.dwBytes            = sizeOfSegmentIdMap;
422         allocParams.pBufName           = "segmentIdStreamOutBuffer";
423         allocParams.ResUsageType       = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
424         m_segmentMapBuffer[segmentBufid] = m_allocator->AllocateResource(allocParams, false);
425 
426         ENCODE_CHK_NULL_RETURN(m_segmentMapBuffer[segmentBufid]);
427 
428         return MOS_STATUS_SUCCESS;
429     }
430 
MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,Av1Segmentation)431     MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, Av1Segmentation)
432     {
433         params.segmentMapStreamInBuffer  = nullptr;
434         params.segmentMapStreamOutBuffer = nullptr;
435 
436         if (m_segmentParams.m_enabled && !m_segmentParams.m_updateMap)
437         {
438             // when segmentation_update_map is 0, send prime_ref_frame's AVP stream out buffer as VDEnc stream in
439             const auto primRefList = m_basicFeature->m_ref.GetPrimaryRefList();
440             ENCODE_CHK_NULL_RETURN(primRefList);
441 
442             params.segmentMapStreamInBuffer = m_segmentMapBuffer[primRefList->m_segIdBufIdx];
443         }
444 
445         return MOS_STATUS_SUCCESS;
446     }
447 
MHW_SETPAR_DECL_SRC(AVP_PIC_STATE,Av1Segmentation)448     MHW_SETPAR_DECL_SRC(AVP_PIC_STATE, Av1Segmentation)
449     {
450         MOS_SecureMemcpy(
451             &params.segmentParams,
452             sizeof(params.segmentParams),
453             &m_segmentParams,
454             sizeof(params.segmentParams));
455 
456         if (m_basicFeature->m_av1PicParams->PicFlags.fields.DisableFrameRecon)
457         {
458             params.segmentParams.m_segIdBufStreamOutEnable = false;
459         }
460 
461 
462         return MOS_STATUS_SUCCESS;
463     }
464 
MHW_SETPAR_DECL_SRC(AVP_SEGMENT_STATE,Av1Segmentation)465     MHW_SETPAR_DECL_SRC(AVP_SEGMENT_STATE, Av1Segmentation)
466     {
467         if (m_segmentNum > av1MaxSegments)
468         {
469             ENCODE_ASSERTMESSAGE("The Segment number exceeds the max value.");
470             return MOS_STATUS_USER_CONTROL_MAX_NAME_SIZE;
471         }
472 
473         params.numSegments = m_segmentNum;
474 
475         MOS_SecureMemcpy(
476             &params.av1SegmentParams,
477             sizeof(params.av1SegmentParams),
478             &m_segmentParams,
479             sizeof(params.av1SegmentParams));
480 
481         return MOS_STATUS_SUCCESS;
482     }
483 
MHW_SETPAR_DECL_SRC(AVP_PIPE_BUF_ADDR_STATE,Av1Segmentation)484     MHW_SETPAR_DECL_SRC(AVP_PIPE_BUF_ADDR_STATE, Av1Segmentation)
485     {
486         ENCODE_CHK_NULL_RETURN(m_basicFeature);
487 
488         if (m_segmentParams.m_segIdBufStreamInEnable)
489         {
490             const auto primRefList = m_basicFeature->m_ref.GetPrimaryRefList();
491             ENCODE_CHK_NULL_RETURN(primRefList);
492             ENCODE_CHK_NULL_RETURN(m_segmentMapBuffer[primRefList->m_segIdBufIdx]);
493             params.segmentIdReadBuffer = m_segmentMapBuffer[primRefList->m_segIdBufIdx];
494         }
495 
496         if (!m_basicFeature->m_av1PicParams->PicFlags.fields.DisableFrameRecon && m_segmentParams.m_segIdBufStreamOutEnable)
497         {
498             const auto currRefList = m_basicFeature->m_ref.GetCurrRefList();
499             ENCODE_CHK_NULL_RETURN(currRefList);
500             ENCODE_CHK_NULL_RETURN(m_segmentMapBuffer[currRefList->m_segIdBufIdx]);
501             params.segmentIdWriteBuffer = m_segmentMapBuffer[currRefList->m_segIdBufIdx];
502         }
503 
504         return MOS_STATUS_SUCCESS;
505     }
506 
MHW_SETPAR_DECL_SRC(VDENC_CMD2,Av1Segmentation)507     MHW_SETPAR_DECL_SRC(VDENC_CMD2, Av1Segmentation)
508     {
509         const auto* picPar = m_basicFeature->m_av1PicParams;
510         ENCODE_CHK_NULL_RETURN(picPar);
511 
512         params.segmentation = m_segmentParams.m_enabled;
513 
514         if (params.segmentation)
515         {
516             // for VP9 VDEnc this is bit used for programming of "segmentation_temporal_update"
517             // for AV1 VDEnc this bit indicates negative of "segmentation_update_map"
518             params.segmentationTemporal =  m_segmentParams.m_updateMap ? false : true;
519 #if _MEDIA_RESERVED
520             params.vdencCmd2Par113 = true;
521 #else
522             params.extSettings.emplace_back(
523                 [this](uint32_t *data) {
524                     data[54] |= 1 << 15;
525                     return MOS_STATUS_SUCCESS;
526                 });
527 #endif  // _MEDIA_RESERVED
528         }
529 
530         for (auto i = 0; i < av1MaxSegments; i++)
531         {
532             if (i < m_segmentNum &&
533                 m_segmentParams.m_enabled &&
534                 (m_segmentParams.m_featureMask[i] & 0x1 /*SEG_LVL_ALT_Q*/))
535             {
536                 uint16_t tempSegQp = picPar->base_qindex + m_segmentParams.m_featureData[i][0];
537                 params.qpForSegs[i] = static_cast<uint8_t> (CodecHal_Clip3(1, 255, tempSegQp));
538 
539 #if _MEDIA_RESERVED
540                 params.vdencCmd2Par99 = 1;
541 #else
542                 params.extSettings.emplace_back(
543                     [this](uint32_t *data) {
544                         data[54] |= 1;
545                         return MOS_STATUS_SUCCESS;
546                     });
547 #endif  // _MEDIA_RESERVED
548             }
549             else
550             {
551                 params.qpForSegs[i] = static_cast<uint8_t>(picPar->base_qindex);
552             }
553         }
554 
555         return MOS_STATUS_SUCCESS;
556     }
557 
558 }  // namespace encode
559