1 /*
2 * Copyright (c) 2020-2021, 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_avc_reference_frames.cpp
24 //! \brief    Defines reference list related logic for encode avc
25 //!
26 
27 #include "encode_avc_reference_frames.h"
28 #include "encode_avc_basic_feature.h"
29 
30 namespace encode
31 {
32 
Init(AvcBasicFeature * basicFeature,EncodeAllocator * allocator)33 MOS_STATUS AvcReferenceFrames::Init(AvcBasicFeature *basicFeature, EncodeAllocator *allocator)
34 {
35     ENCODE_FUNC_CALL();
36     ENCODE_CHK_NULL_RETURN(basicFeature);
37 
38     m_basicFeature = basicFeature;
39     m_allocator    = allocator;
40     ENCODE_CHK_NULL_RETURN(m_allocator);
41     ENCODE_CHK_STATUS_RETURN(EncodeAllocateDataList(
42         m_refList,
43         CODEC_AVC_NUM_UNCOMPRESSED_SURFACE));
44 
45     return MOS_STATUS_SUCCESS;
46 }
47 
~AvcReferenceFrames()48 AvcReferenceFrames::~AvcReferenceFrames()
49 {
50     ENCODE_FUNC_CALL();
51 
52     EncodeFreeDataList(m_refList, CODEC_AVC_NUM_UNCOMPRESSED_SURFACE);
53 }
54 
UpdatePicture()55 MOS_STATUS AvcReferenceFrames::UpdatePicture()
56 {
57     ENCODE_FUNC_CALL();
58 
59     auto picParams = m_basicFeature->m_picParam;
60     auto avcRefList = &m_refList[0];
61     auto avcPicIdx  = &m_picIdx[0];
62 
63     auto prevPic    = m_basicFeature->m_currOriginalPic;
64     auto prevIdx    = prevPic.FrameIdx;
65     auto currPic    = picParams->CurrOriginalPic;
66     auto currIdx    = currPic.FrameIdx;
67 
68     uint8_t prevRefIdx = m_basicFeature->m_currReconstructedPic.FrameIdx;
69     uint8_t currRefIdx = picParams->CurrReconstructedPic.FrameIdx;
70 
71     avcRefList[currRefIdx]->sRefReconBuffer = m_basicFeature->m_reconSurface;
72     avcRefList[currRefIdx]->sRefRawBuffer   = m_basicFeature->m_rawSurface;
73     avcRefList[currRefIdx]->sFrameNumber    = picParams->frame_num;
74     avcRefList[currRefIdx]->RefPic          = picParams->CurrOriginalPic;
75 
76     // P/B frames with empty ref lists are internally encoded as I frames,
77     // while picture header packing remains the original value
78     m_pictureCodingType = picParams->CodingType;
79 
80     bool emptyRefFrmList = true;
81     for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
82     {
83         if (picParams->RefFrameList[i].PicFlags != PICTURE_INVALID)
84         {
85             emptyRefFrmList = false;
86             break;
87         }
88     }
89 
90     if (emptyRefFrmList && m_pictureCodingType != I_TYPE)
91     {
92         m_pictureCodingType = I_TYPE;
93     }
94 
95     avcRefList[currRefIdx]->bUsedAsRef         = picParams->RefPicFlag;
96     avcRefList[currRefIdx]->resBitstreamBuffer = m_basicFeature->m_resBitstreamBuffer;
97 
98     for (uint8_t i = 0; i < 16; i++)
99     {
100         m_frameStoreID[i].inUse = false;
101     }
102 
103     for (uint8_t i = 0; i < 16; i++)
104     {
105         avcPicIdx[i].bValid = false;
106         if (picParams->RefFrameList[i].PicFlags != PICTURE_INVALID)
107         {
108             auto    index         = picParams->RefFrameList[i].FrameIdx;
109             uint8_t duplicatedIdx = 0;
110             for (uint8_t ii = 0; ii < i; ii++)
111             {
112                 if (avcPicIdx[ii].bValid && index == picParams->RefFrameList[ii].FrameIdx)
113                 {
114                     duplicatedIdx = 1;
115                     break;
116                 }
117             }
118             if (duplicatedIdx)
119             {
120                 continue;
121             }
122 
123             avcRefList[index]->RefPic.PicFlags =
124                 CodecHal_CombinePictureFlags(avcRefList[index]->RefPic, picParams->RefFrameList[i]);
125             avcRefList[index]->iFieldOrderCnt[0] = picParams->FieldOrderCntList[i][0];
126             avcRefList[index]->iFieldOrderCnt[1] = picParams->FieldOrderCntList[i][1];
127             avcPicIdx[i].bValid                  = true;
128             avcPicIdx[i].ucPicIdx                = index;
129             if (prevPic.PicFlags != PICTURE_INVALID)
130             {
131                 uint8_t ii;
132                 for (ii = 0; ii < avcRefList[prevRefIdx]->ucNumRef; ii++)
133                 {
134                     if (index == avcRefList[prevRefIdx]->RefList[ii].FrameIdx)
135                     {
136                         if (avcRefList[index]->ucFrameId == 0x1f)
137                         {
138                             // Should never happen, something must be wrong
139                             ENCODE_ASSERT(false);
140                             avcRefList[index]->ucFrameId = 0;
141                         }
142                         m_frameStoreID[avcRefList[index]->ucFrameId].inUse = true;
143                         break;
144                     }
145                 }
146                 if (ii == avcRefList[prevRefIdx]->ucNumRef)
147                 {
148                     avcRefList[index]->ucFrameId = 0x1f;
149                 }
150             }
151         }
152     }
153 
154     // Save the current RefList
155     uint8_t ii = 0;
156     for (uint8_t i = 0; i < 16; i++)
157     {
158         if (avcPicIdx[i].bValid)
159         {
160             avcRefList[currRefIdx]->RefList[ii] = picParams->RefFrameList[i];
161             ii++;
162         }
163     }
164     avcRefList[currRefIdx]->ucNumRef = ii;
165     m_currRefList                    = avcRefList[currRefIdx];
166 
167     ENCODE_CHK_STATUS_RETURN(SetFrameStoreIds(currRefIdx));
168 
169     avcRefList[currRefIdx]->iFieldOrderCnt[0]     = picParams->CurrFieldOrderCnt[0];
170     avcRefList[currRefIdx]->iFieldOrderCnt[1]     = picParams->CurrFieldOrderCnt[1];
171 
172     m_refList[currRefIdx]->ucAvcPictureCodingType =
173         CodecHal_PictureIsFrame(picParams->CurrOriginalPic) ?
174         CODEC_AVC_PIC_CODING_TYPE_FRAME :
175         ((picParams->CurrFieldOrderCnt[0] < picParams->CurrFieldOrderCnt[1]) ?
176             CODEC_AVC_PIC_CODING_TYPE_TFF_FIELD :
177             CODEC_AVC_PIC_CODING_TYPE_BFF_FIELD);
178 
179     if (m_pictureCodingType == B_TYPE)
180     {
181         GetDistScaleFactor();
182         m_biWeight = GetBiWeight(
183             m_distScaleFactorList0[0],
184             picParams->weighted_bipred_idc);
185     }
186 
187     avcRefList[currRefIdx]->pRefPicSelectListEntry = nullptr;
188 
189     return MOS_STATUS_SUCCESS;
190 }
191 
UpdateSlice()192 MOS_STATUS AvcReferenceFrames::UpdateSlice()
193 {
194     ENCODE_FUNC_CALL();
195 
196     auto slcParams = m_basicFeature->m_sliceParams;
197     auto seqParams = m_basicFeature->m_seqParam;
198     auto picParams = m_basicFeature->m_picParam;
199 
200     if (m_pictureCodingType != I_TYPE)
201     {
202         CODECHAL_ENCODE_AVC_VALIDATE_NUM_REFS_PARAMS validateNumRefsParams;
203         validateNumRefsParams.pSeqParams            = seqParams;
204         validateNumRefsParams.pPicParams            = picParams;
205         validateNumRefsParams.pAvcSliceParams       = slcParams;
206         validateNumRefsParams.wPictureCodingType    = m_pictureCodingType;
207         validateNumRefsParams.wPicHeightInMB        = m_basicFeature->m_picHeightInMb;
208         validateNumRefsParams.wFrameFieldHeightInMB = m_basicFeature->m_frameFieldHeightInMb;
209         validateNumRefsParams.bVDEncEnabled         = true;
210 
211         ENCODE_CHK_STATUS_RETURN(ValidateNumReferences(&validateNumRefsParams));
212     }
213     else
214     {
215         slcParams->num_ref_idx_l0_active_minus1 = 0;
216         slcParams->num_ref_idx_l1_active_minus1 = 0;
217     }
218 
219     // Save the QP value
220     if (CodecHal_PictureIsBottomField(picParams->CurrOriginalPic))
221     {
222         m_refList[m_basicFeature->m_currReconstructedPic.FrameIdx]->ucQPValue[1] =
223             picParams->pic_init_qp_minus26 + 26 + slcParams->slice_qp_delta;
224     }
225     else
226     {
227         m_refList[m_basicFeature->m_currReconstructedPic.FrameIdx]->ucQPValue[0] =
228             picParams->pic_init_qp_minus26 + 26 + slcParams->slice_qp_delta;
229     }
230 
231     for (uint32_t sliceCount = 0; sliceCount < m_basicFeature->m_numSlices; sliceCount++)
232     {
233         if (m_pictureCodingType != I_TYPE)
234         {
235             for (uint8_t i = 0; i < (slcParams->num_ref_idx_l0_active_minus1 + 1); i++)
236             {
237                 slcParams->PicOrder[0][i].Picture.FrameIdx =
238                     m_picIdx[slcParams->RefPicList[0][i].FrameIdx].ucPicIdx;
239                 slcParams->PicOrder[0][i].Picture.PicFlags =
240                     slcParams->RefPicList[0][i].PicFlags;
241             }
242         }
243         if (m_pictureCodingType == B_TYPE)
244         {
245             for (uint8_t i = 0; i < (slcParams->num_ref_idx_l1_active_minus1 + 1); i++)
246             {
247                 slcParams->PicOrder[1][i].Picture.FrameIdx =
248                     m_picIdx[slcParams->RefPicList[1][i].FrameIdx].ucPicIdx;
249                 slcParams->PicOrder[1][i].Picture.PicFlags =
250                     slcParams->RefPicList[1][i].PicFlags;
251             }
252         }
253         slcParams++;
254     }
255 
256     if (seqParams->NumRefFrames == CODEC_AVC_MAX_NUM_REF_FRAME)
257     {
258         const uint8_t hwInvalidFrameId              = CODEC_AVC_MAX_NUM_REF_FRAME - 1;
259         slcParams                                   = m_basicFeature->m_sliceParams;
260         bool          isActiveRef[hwInvalidFrameId] = {};
261         uint8_t       swapIndex                     = CODEC_AVC_NUM_UNCOMPRESSED_SURFACE;
262         for (uint32_t sliceCount = 0; sliceCount < m_basicFeature->m_numSlices; sliceCount++)
263         {
264             if (m_pictureCodingType != I_TYPE)
265             {
266                 for (uint8_t i = 0; i < (slcParams->num_ref_idx_l0_active_minus1 + 1); i++)
267                 {
268                     auto index = m_picIdx[slcParams->RefPicList[0][i].FrameIdx].ucPicIdx;
269                     if (m_refList[index]->ucFrameId < hwInvalidFrameId)
270                     {
271                         isActiveRef[m_refList[index]->ucFrameId] = true;
272                     }
273                     else if (m_refList[index]->ucFrameId == hwInvalidFrameId && swapIndex == CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)
274                     {
275                         swapIndex = index;
276                     }
277                     else
278                     {
279                         // should never happen, something must be wrong
280                         CODECHAL_PUBLIC_ASSERT(false);
281                     }
282                 }
283             }
284             if (m_pictureCodingType == B_TYPE)
285             {
286                 for (uint8_t i = 0; i < (slcParams->num_ref_idx_l1_active_minus1 + 1); i++)
287                 {
288                     auto index = m_picIdx[slcParams->RefPicList[1][i].FrameIdx].ucPicIdx;
289                     if (m_refList[index]->ucFrameId < hwInvalidFrameId)
290                     {
291                         isActiveRef[m_refList[index]->ucFrameId] = true;
292                     }
293                     else if (m_refList[index]->ucFrameId == hwInvalidFrameId && swapIndex == CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)
294                     {
295                         swapIndex = index;
296                     }
297                     else
298                     {
299                         // should never happen, something must be wrong
300                         CODECHAL_PUBLIC_ASSERT(false);
301                     }
302                 }
303             }
304             slcParams++;
305         }
306 
307         if (swapIndex < CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)
308         {
309             uint8_t i = 0;
310             for (i = 0; i < hwInvalidFrameId; i++)
311             {
312                 if (isActiveRef[i])
313                 {
314                     continue;
315                 }
316                 uint8_t j = 0;
317                 for (j = 0; j < CODEC_AVC_MAX_NUM_REF_FRAME; j++)
318                 {
319                     if (m_picIdx[j].bValid && m_refList[m_picIdx[j].ucPicIdx]->ucFrameId == i)
320                     {
321                         std::swap(m_refList[m_picIdx[j].ucPicIdx]->ucFrameId, m_refList[swapIndex]->ucFrameId);
322                         break;
323                     }
324                 }
325                 if (j != CODEC_AVC_MAX_NUM_REF_FRAME)
326                 {
327                     break;
328                 }
329             }
330             if (i == hwInvalidFrameId)
331             {
332                 // should never happen, something must be wrong
333                 CODECHAL_PUBLIC_ASSERT(false);
334             }
335         }
336     }
337 
338     return MOS_STATUS_SUCCESS;
339 }
340 
GetDistScaleFactor()341 void AvcReferenceFrames::GetDistScaleFactor()
342 {
343     auto picParams = m_basicFeature->m_picParam;
344     auto slcParams = m_basicFeature->m_sliceParams;
345     auto refList   = &(m_refList[0]);
346     auto picIdx    = &(m_picIdx[0]);
347 
348     bool bottom  = CodecHal_PictureIsBottomField(picParams->CurrOriginalPic);
349     int  pocCurr = picParams->CurrFieldOrderCnt[bottom];
350 
351     MOS_ZeroMemory(m_distScaleFactorList0, sizeof(uint32_t) * CODEC_AVC_MAX_NUM_REF_FRAME * 2);
352     for (unsigned int index = 0; index <= slcParams->num_ref_idx_l0_active_minus1; index++)
353     {
354         auto picture = slcParams->RefPicList[LIST_0][index];
355         if (!CodecHal_PictureIsInvalid(picture))
356         {
357             auto pictureIdx = picIdx[picture.FrameIdx].ucPicIdx;
358             int  pocPic0    = CodecHal_PictureIsBottomField(picture) ? refList[pictureIdx]->iFieldOrderCnt[1] : refList[pictureIdx]->iFieldOrderCnt[0];
359             picture         = slcParams->RefPicList[LIST_1][0];
360             pictureIdx      = picIdx[picture.FrameIdx].ucPicIdx;
361             int pocPic1     = CodecHal_PictureIsBottomField(picture) ? refList[pictureIdx]->iFieldOrderCnt[1] : refList[pictureIdx]->iFieldOrderCnt[0];
362             int tb          = CodecHal_Clip3(-128, 127, (pocCurr - pocPic0));
363             int td          = CodecHal_Clip3(-128, 127, (pocPic1 - pocPic0));
364             if (td == 0)
365             {
366                 td = 1;
367             }
368             int tx = (16384 + ABS(td / 2)) / td;
369 
370             m_distScaleFactorList0[index] = CodecHal_Clip3(-1024, 1023, (tb * tx + 32) >> 6);
371         }
372     }
373 }
374 
GetBiWeight(uint32_t distScaleFactorRefID0List0,uint16_t weightedBiPredIdc)375 int32_t AvcReferenceFrames::GetBiWeight(
376     uint32_t distScaleFactorRefID0List0,
377     uint16_t weightedBiPredIdc)
378 {
379     int32_t biWeight = 32;  // default value
380     if (weightedBiPredIdc != IMPLICIT_WEIGHTED_INTER_PRED_MODE)
381     {
382         biWeight = 32;
383     }
384     else
385     {
386         biWeight = (distScaleFactorRefID0List0 + 2) >> 2;
387 
388         if (biWeight != 16 && biWeight != 21 &&
389             biWeight != 32 && biWeight != 43 && biWeight != 48)
390         {
391             biWeight = 32;  // If # of B-pics between two refs is more than 3. VME does not support it.
392         }
393     }
394 
395     return biWeight;
396 }
397 
SetFrameStoreIds(uint8_t frameIdx)398 MOS_STATUS AvcReferenceFrames::SetFrameStoreIds(uint8_t frameIdx)
399 {
400     uint8_t invalidFrame = (m_basicFeature->m_mode == CODECHAL_DECODE_MODE_AVCVLD) ? 0x7f : 0x1f;
401 
402     for (uint8_t i = 0; i < m_refList[frameIdx]->ucNumRef; i++)
403     {
404         uint8_t index;
405         index = m_refList[frameIdx]->RefList[i].FrameIdx;
406         if (m_refList[index]->ucFrameId == invalidFrame)
407         {
408             uint8_t j;
409             for (j = 0; j < CODEC_AVC_MAX_NUM_REF_FRAME; j++)
410             {
411                 if (!m_frameStoreID[j].inUse)
412                 {
413                     m_refList[index]->ucFrameId = j;
414                     m_frameStoreID[j].inUse  = true;
415                     break;
416                 }
417             }
418             if (j == CODEC_AVC_MAX_NUM_REF_FRAME)
419             {
420                 // should never happen, something must be wrong
421                 CODECHAL_PUBLIC_ASSERT(false);
422                 m_refList[index]->ucFrameId = 0;
423                 m_frameStoreID[0].inUse  = true;
424             }
425         }
426     }
427     return MOS_STATUS_SUCCESS;
428 }
429 
ValidateNumReferences(PCODECHAL_ENCODE_AVC_VALIDATE_NUM_REFS_PARAMS params)430 MOS_STATUS AvcReferenceFrames::ValidateNumReferences(PCODECHAL_ENCODE_AVC_VALIDATE_NUM_REFS_PARAMS params)
431 {
432     MOS_STATUS        eStatus             = MOS_STATUS_SUCCESS;
433     constexpr uint8_t MaxNumRefPMinusOne  = 2;  // caps.MaxNum_Reference0-1 for all TUs
434     constexpr uint8_t MaxNumRefB0MinusOne = 0;  // no corresponding caps
435     constexpr uint8_t MaxNumRefB1MinusOne = 0;  // caps.MaxNum_Reference1-1 for all TUs
436 
437     ENCODE_FUNC_CALL();
438     ENCODE_CHK_NULL_RETURN(params);
439     ENCODE_CHK_NULL_RETURN(params->pAvcSliceParams);
440 
441     uint8_t numRefIdx0MinusOne = params->pAvcSliceParams->num_ref_idx_l0_active_minus1;
442     uint8_t numRefIdx1MinusOne = params->pAvcSliceParams->num_ref_idx_l1_active_minus1;
443 
444     if (params->wPictureCodingType == P_TYPE)
445     {
446         if (numRefIdx0MinusOne > MaxNumRefPMinusOne)
447         {
448             ENCODE_NORMALMESSAGE("Invalid active reference list size (P).");
449             numRefIdx0MinusOne = MaxNumRefPMinusOne;
450         }
451 
452         numRefIdx1MinusOne = 0;
453     }
454     else if (params->wPictureCodingType == B_TYPE)
455     {
456         if (numRefIdx0MinusOne > MaxNumRefB0MinusOne)
457         {
458             ENCODE_NORMALMESSAGE("Invalid active reference list size (B0).");
459             numRefIdx0MinusOne = MaxNumRefB0MinusOne;
460         }
461 
462         if (numRefIdx1MinusOne > MaxNumRefB1MinusOne)
463         {
464             ENCODE_NORMALMESSAGE("Invalid active reference list1 size (B1).");
465             numRefIdx1MinusOne = MaxNumRefB1MinusOne;
466         }
467     }
468 
469     params->pAvcSliceParams->num_ref_idx_l0_active_minus1 = numRefIdx0MinusOne;
470     params->pAvcSliceParams->num_ref_idx_l1_active_minus1 = numRefIdx1MinusOne;
471 
472     return eStatus;
473 }
474 
MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,AvcReferenceFrames)475 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, AvcReferenceFrames)
476 {
477     ENCODE_FUNC_CALL();
478 
479     ENCODE_CHK_NULL_RETURN(m_basicFeature);
480 
481     auto trackedBuf = m_basicFeature->m_trackedBuf;
482     ENCODE_CHK_NULL_RETURN(trackedBuf);
483 
484     auto slcParams = m_basicFeature->m_sliceParams;
485     ENCODE_CHK_NULL_RETURN(slcParams);
486 
487     if (m_pictureCodingType != I_TYPE)
488     {
489         // populate the RefPic and DS surface so pfnAddVdencPipeBufAddrCmd() can directly use them
490         auto l0RefFrameList = slcParams->RefPicList[LIST_0];
491         for (uint8_t refIdx = 0; refIdx <= slcParams->num_ref_idx_l0_active_minus1; refIdx++)
492         {
493             auto refPic = l0RefFrameList[refIdx];
494 
495             if (!CodecHal_PictureIsInvalid(refPic) && m_picIdx[refPic.FrameIdx].bValid)
496             {
497                 // L0 references
498                 auto refPicIdx                    = m_picIdx[refPic.FrameIdx].ucPicIdx;
499                 params.refs[refIdx] = &m_refList[refPicIdx]->sRefReconBuffer.OsResource;
500                 m_allocator->UpdateResourceUsageType(&m_refList[refPicIdx]->sRefReconBuffer.OsResource, MOS_HW_RESOURCE_USAGE_ENCODE_INPUT_RECON);
501 
502                 // 4x DS surface for VDEnc
503                 uint8_t scaledIdx = m_refList[refPicIdx]->ucScalingIdx;
504                 auto vdenc4xDsSurface = trackedBuf->GetSurface(BufferType::ds4xSurface, scaledIdx);
505                 ENCODE_CHK_NULL_RETURN(vdenc4xDsSurface);
506                 params.refsDsStage1[refIdx] = &vdenc4xDsSurface->OsResource;
507             }
508         }
509     }
510 
511     if (m_pictureCodingType == B_TYPE)
512     {
513         auto l1RefFrameList = slcParams->RefPicList[LIST_1];
514         auto l0RefNum = slcParams->num_ref_idx_l0_active_minus1 + 1;
515         for (uint8_t refIdx = 0; refIdx <= slcParams->num_ref_idx_l1_active_minus1; refIdx++)
516         {
517             auto refPic = l1RefFrameList[refIdx];
518 
519             if (!CodecHal_PictureIsInvalid(refPic) && m_picIdx[refPic.FrameIdx].bValid)
520             {
521                 // L1 references
522                 auto refPicIdx = m_picIdx[refPic.FrameIdx].ucPicIdx;
523                 params.refs[l0RefNum + refIdx] = &m_refList[refPicIdx]->sRefReconBuffer.OsResource;
524                 m_allocator->UpdateResourceUsageType(&m_refList[refPicIdx]->sRefReconBuffer.OsResource, MOS_HW_RESOURCE_USAGE_ENCODE_INPUT_RECON);
525 
526                 // 4x DS surface for VDEnc
527                 uint8_t scaledIdx = m_refList[refPicIdx]->ucScalingIdx;
528                 auto vdenc4xDsSurface = trackedBuf->GetSurface(BufferType::ds4xSurface, scaledIdx);
529                 ENCODE_CHK_NULL_RETURN(vdenc4xDsSurface);
530                 params.refsDsStage1[l0RefNum + refIdx] = &vdenc4xDsSurface->OsResource;
531             }
532         }
533     }
534 
535     return MOS_STATUS_SUCCESS;
536 }
537 
MHW_SETPAR_DECL_SRC(VDENC_AVC_IMG_STATE,AvcReferenceFrames)538 MHW_SETPAR_DECL_SRC(VDENC_AVC_IMG_STATE, AvcReferenceFrames)
539 {
540     auto picParams = m_basicFeature->m_picParam;
541     auto slcParams = m_basicFeature->m_sliceParams;
542     uint8_t refPoc[2][3] = {};
543 
544     if (picParams->CodingType != I_TYPE)
545     {
546         params.numberOfL0ReferencesMinusOne = slcParams->num_ref_idx_l0_active_minus1;
547         params.numberOfL1ReferencesMinusOne = slcParams->num_ref_idx_l1_active_minus1;
548 
549         MHW_CHK_STATUS_RETURN(slcParams->num_ref_idx_l0_active_minus1 > 2);
550         uint8_t fwdRefIdx[3] = {0xf, 0xf, 0xf};
551         for (auto i = 0; i < slcParams->num_ref_idx_l0_active_minus1 + 1; i++)
552         {
553             auto id = slcParams->RefPicList[LIST_0][i].FrameIdx;
554             id = m_picIdx[id].ucPicIdx;
555             fwdRefIdx[i] = m_refList[id]->ucFrameId;
556             refPoc[0][i] = (uint8_t)m_refList[id]->iFieldOrderCnt[0];
557         }
558         params.fwdRefIdx0ReferencePicture = fwdRefIdx[0];
559         params.fwdRefIdx1ReferencePicture = fwdRefIdx[1];
560         params.fwdRefIdx2ReferencePicture = fwdRefIdx[2];
561 
562         if (picParams->CodingType == B_TYPE)
563         {
564             auto id = slcParams->RefPicList[LIST_1][0].FrameIdx;
565             params.longtermReferenceFrameBwdRef0Indicator = (id < CODEC_AVC_MAX_NUM_REF_FRAME) && CodecHal_PictureIsLongTermRef(picParams->RefFrameList[id]);
566             if (id >= CODEC_AVC_MAX_NUM_REF_FRAME)
567             {
568                 return MOS_STATUS_INVALID_PARAMETER;
569             }
570             id = m_picIdx[id].ucPicIdx;
571             params.bwdRefIdx0ReferencePicture = m_refList[id]->ucFrameId;
572             refPoc[1][0] = (uint8_t)m_refList[id]->iFieldOrderCnt[0];
573         }
574     }
575 
576     params.pocNumberForCurrentPicture = (uint8_t)m_refList[picParams->CurrReconstructedPic.FrameIdx]->iFieldOrderCnt[0];
577     params.pocNumberForFwdRef0 = refPoc[0][0];
578     params.pocNumberForFwdRef1 = refPoc[0][1];
579     params.pocNumberForFwdRef2 = refPoc[0][2];
580     params.pocNumberForBwdRef0 = refPoc[1][0];
581 
582     return MOS_STATUS_SUCCESS;
583 }
584 
MHW_SETPAR_DECL_SRC(MFX_PIPE_BUF_ADDR_STATE,AvcReferenceFrames)585 MHW_SETPAR_DECL_SRC(MFX_PIPE_BUF_ADDR_STATE, AvcReferenceFrames)
586 {
587     ENCODE_FUNC_CALL();
588 
589     ENCODE_CHK_NULL_RETURN(m_basicFeature);
590 
591     auto trackedBuf = m_basicFeature->m_trackedBuf;
592     ENCODE_CHK_NULL_RETURN(trackedBuf);
593 
594     auto firstValidFrame = &m_basicFeature->m_reconSurface.OsResource;
595     auto slcParams = m_basicFeature->m_sliceParams;
596     ENCODE_CHK_NULL_RETURN(slcParams);
597 
598     // Setting invalid entries to nullptr
599     for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
600         params.presReferences[i] = nullptr;
601 
602     uint8_t firstValidFrameId = CODEC_AVC_MAX_NUM_REF_FRAME;
603 
604     for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
605     {
606         if (m_picIdx[i].bValid)
607         {
608             auto picIdx       = m_picIdx[i].ucPicIdx;
609             auto frameStoreId = m_refList[picIdx]->ucFrameId;
610 
611             params.presReferences[frameStoreId] = &(m_refList[picIdx]->sRefReconBuffer.OsResource);
612             m_allocator->UpdateResourceUsageType(&m_refList[picIdx]->sRefReconBuffer.OsResource, MOS_HW_RESOURCE_USAGE_ENCODE_INPUT_RECON);
613 
614             if (picIdx < firstValidFrameId)
615             {
616                 firstValidFrameId = picIdx;
617                 firstValidFrame   = params.presReferences[picIdx];
618             }
619         }
620     }
621 
622     for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
623     {
624         // error concealment for the unset reference addresses
625         if (!params.presReferences[i])
626         {
627             params.presReferences[i] = firstValidFrame;
628         }
629     }
630 
631     if (m_pictureCodingType != I_TYPE)
632     {
633         // populate the RefPic and DS surface so pfnAddVdencPipeBufAddrCmd() can directly use them
634         auto l0RefFrameList = slcParams->RefPicList[LIST_0];
635         for (uint8_t refIdx = 0; refIdx <= slcParams->num_ref_idx_l0_active_minus1; refIdx++)
636         {
637             auto refPic = l0RefFrameList[refIdx];
638 
639             if (!CodecHal_PictureIsInvalid(refPic) && m_picIdx[refPic.FrameIdx].bValid)
640             {
641                 // L0 references
642                 auto refPicIdx                    = m_picIdx[refPic.FrameIdx].ucPicIdx;
643                 params.presVdencReferences[refIdx] = &m_refList[refPicIdx]->sRefReconBuffer.OsResource;
644                 m_allocator->UpdateResourceUsageType(&m_refList[refPicIdx]->sRefReconBuffer.OsResource, MOS_HW_RESOURCE_USAGE_ENCODE_INPUT_RECON);
645             }
646         }
647     }
648 
649     if (m_pictureCodingType == B_TYPE)
650     {
651         auto l1RefFrameList = slcParams->RefPicList[LIST_1];
652         auto l0RefNum = slcParams->num_ref_idx_l0_active_minus1 + 1;
653         for (uint8_t refIdx = 0; refIdx <= slcParams->num_ref_idx_l1_active_minus1; refIdx++)
654         {
655             auto refPic = l1RefFrameList[refIdx];
656 
657             if (!CodecHal_PictureIsInvalid(refPic) && m_picIdx[refPic.FrameIdx].bValid)
658             {
659                 // L1 references
660                 auto refPicIdx = m_picIdx[refPic.FrameIdx].ucPicIdx;
661                 params.presVdencReferences[l0RefNum + refIdx] = &m_refList[refPicIdx]->sRefReconBuffer.OsResource;
662                 m_allocator->UpdateResourceUsageType(&m_refList[refPicIdx]->sRefReconBuffer.OsResource, MOS_HW_RESOURCE_USAGE_ENCODE_INPUT_RECON);
663             }
664         }
665     }
666 
667     return MOS_STATUS_SUCCESS;
668 }
669 
670 }  // namespace encode
671