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