1 /*
2 * Copyright (c) 2018, 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_hevc_reference_frames.cpp
24 //! \brief Defines reference list related logic for encode hevc
25 //!
26
27 #include "encode_hevc_basic_feature.h"
28 #include "encode_utils.h"
29 #include "encode_hevc_reference_frames.h"
30 #include "codec_def_encode_hevc.h"
31 #include "encode_hevc_dfs.h"
32
33 namespace encode
34 {
Init(HevcBasicFeature * basicFeature,EncodeAllocator * allocator)35 MOS_STATUS HevcReferenceFrames::Init(HevcBasicFeature *basicFeature, EncodeAllocator *allocator)
36 {
37 ENCODE_FUNC_CALL();
38 ENCODE_CHK_NULL_RETURN(basicFeature);
39
40 m_basicFeature = basicFeature;
41 m_allocator = allocator;
42 ENCODE_CHK_NULL_RETURN(m_allocator);
43 ENCODE_CHK_STATUS_RETURN(EncodeAllocateDataList(
44 m_refList,
45 CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC));
46
47 return MOS_STATUS_SUCCESS;
48
49 }
~HevcReferenceFrames()50 HevcReferenceFrames::~HevcReferenceFrames()
51 {
52 ENCODE_FUNC_CALL();
53
54 EncodeFreeDataList(m_refList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC);
55
56 }
57
UpdatePicture()58 MOS_STATUS HevcReferenceFrames::UpdatePicture()
59 {
60 ENCODE_FUNC_CALL();
61
62 auto picParams = m_basicFeature->m_hevcPicParams;
63 ENCODE_CHK_NULL_RETURN(picParams);
64
65 PCODEC_REF_LIST *refListFull = &m_refList[0];
66 m_currRefIdx = picParams->CurrReconstructedPic.FrameIdx;
67 m_currRefList = refListFull[m_currRefIdx];
68
69 // P/B frames with empty ref lists are internally encoded as I frames,
70 // while picture header packing remains the original value
71 m_pictureCodingType = picParams->CodingType;
72
73 bool emptyRefFrmList = true;
74 for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
75 {
76 if (picParams->RefFrameList[i].PicFlags != PICTURE_INVALID)
77 {
78 emptyRefFrmList = false;
79 break;
80 }
81 }
82
83 if (emptyRefFrmList)
84 {
85 // If there is no reference frame in the list, just mark the current picture as the I type
86 m_pictureCodingType = I_TYPE;
87 }
88
89 for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
90 {
91 m_picIdx[i].bValid = false;
92 if (picParams->RefFrameList[i].PicFlags != PICTURE_INVALID)
93 {
94 uint8_t index = picParams->RefFrameList[i].FrameIdx;
95 bool duplicatedIdx = false;
96 for (auto ii = 0; ii < i; ii++)
97 {
98 if (m_picIdx[ii].bValid && index == picParams->RefFrameList[ii].FrameIdx)
99 {
100 // We find the same FrameIdx in the ref_frame_list. Multiple reference frames are the same.
101 // In other words, RefFrameList[i] and RefFrameList[ii] have the same surface Id
102 duplicatedIdx = true;
103 break;
104 }
105 }
106
107 if (duplicatedIdx)
108 {
109 continue;
110 }
111
112 // this reference frame in unique. Save it into the full reference list with 127 items
113 refListFull[index]->RefPic.PicFlags =
114 CodecHal_CombinePictureFlags(refListFull[index]->RefPic, picParams->RefFrameList[i]);
115 refListFull[index]->iFieldOrderCnt[0] = picParams->RefFramePOCList[i];
116 refListFull[index]->iFieldOrderCnt[1] = picParams->RefFramePOCList[i];
117 refListFull[index]->sRefBuffer = picParams->bUseRawPicForRef ? refListFull[index]->sRefRawBuffer : refListFull[index]->sRefReconBuffer;
118
119 m_picIdx[i].bValid = true;
120 m_picIdx[i].ucPicIdx = index;
121 }
122 }
123
124 // Save the current RefList
125 uint8_t ii = 0;
126 for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
127 {
128 if (m_picIdx[i].bValid)
129 {
130 refListFull[m_currRefIdx]->RefList[ii] = picParams->RefFrameList[i];
131 ii++;
132 }
133 }
134
135 m_currRefList->RefPic = picParams->CurrOriginalPic;
136 m_currRefList->bUsedAsRef = picParams->bUsedAsRef;
137 m_currRefList->bFormatConversionDone = false;
138 m_currRefList->ucNumRef = ii;
139 m_currRefList->iFieldOrderCnt[0] = picParams->CurrPicOrderCnt;
140 m_currRefList->iFieldOrderCnt[1] = picParams->CurrPicOrderCnt;
141 m_currRefList->sRefReconBuffer = m_basicFeature->m_reconSurface;
142 m_currRefList->sRefRawBuffer = m_basicFeature->m_rawSurface;
143 m_currRefList->resBitstreamBuffer = m_basicFeature->m_resBitstreamBuffer;
144
145 return MOS_STATUS_SUCCESS;
146
147 }
148
UpdateSlice()149 MOS_STATUS HevcReferenceFrames::UpdateSlice()
150 {
151 ENCODE_FUNC_CALL();
152 auto picParams = m_basicFeature->m_hevcPicParams;
153 ENCODE_CHK_NULL_RETURN(picParams);
154 auto sliceParams = m_basicFeature->m_hevcSliceParams;
155 ENCODE_CHK_NULL_RETURN(sliceParams);
156
157 m_lowDelay = true;
158 m_sameRefList = true;
159
160 for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
161 {
162 m_refIdxMapping[i] = -1;
163 m_currUsedRefPic[i] = false;
164 }
165
166 // To obtain current "used" reference frames. The number of current used reference frames cannot be greater than 8
167 auto slcParams = sliceParams;
168 for (uint32_t s = 0; s < m_basicFeature->m_numSlices; s++, slcParams++)
169 {
170 for (uint8_t ll = 0; ll < 2; ll++)
171 {
172 uint32_t numRef = (ll == 0) ? slcParams->num_ref_idx_l0_active_minus1 :
173 slcParams->num_ref_idx_l1_active_minus1;
174
175 for (uint32_t i = 0; i <= numRef; i++)
176 {
177 CODEC_PICTURE refPic = slcParams->RefPicList[ll][i];
178 if (!CodecHal_PictureIsInvalid(refPic) &&
179 !CodecHal_PictureIsInvalid(picParams->RefFrameList[refPic.FrameIdx]))
180 {
181 m_currUsedRefPic[refPic.FrameIdx] = true;
182 }
183 }
184 }
185 }
186
187 for (uint8_t i = 0, refIdx = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
188 {
189 if (!m_currUsedRefPic[i])
190 {
191 continue;
192 }
193
194 uint8_t index = picParams->RefFrameList[i].FrameIdx;
195 bool duplicatedIdx = false;
196 for (uint8_t ii = 0; ii < i; ii++)
197 {
198 if (m_currUsedRefPic[i] && index == picParams->RefFrameList[ii].FrameIdx)
199 {
200 // We find the same FrameIdx in the ref_frame_list. Multiple reference frames are the same.
201 // In other words, RefFrameList[i] and RefFrameList[ii] have the same surface Id
202 duplicatedIdx = true;
203 m_refIdxMapping[i] = m_refIdxMapping[ii];
204 break;
205 }
206 }
207
208 if (duplicatedIdx)
209 {
210 continue;
211 }
212
213 if (refIdx >= CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC)
214 {
215 // Total number of distingushing reference frames cannot be geater than 8.
216 ENCODE_ASSERT(false);
217 return MOS_STATUS_INVALID_PARAMETER;
218 }
219
220 // Map reference frame index [0-15] into a set of unique IDs within [0-7]
221 m_refIdxMapping[i] = refIdx;
222 refIdx++;
223 }
224
225 if (m_pictureCodingType != I_TYPE && picParams->CollocatedRefPicIndex != 0xFF && picParams->CollocatedRefPicIndex < CODEC_MAX_NUM_REF_FRAME_HEVC)
226 {
227 uint8_t frameStoreId = (uint8_t)m_refIdxMapping[picParams->CollocatedRefPicIndex];
228
229 if (frameStoreId >= CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC || !m_currUsedRefPic[picParams->CollocatedRefPicIndex])
230 {
231 // CollocatedRefPicIndex is wrong in this case for the reference frame is not used be used
232 return MOS_STATUS_INVALID_PARAMETER;
233 }
234 }
235
236 m_currRefList->ucQPValue[0] = picParams->QpY + sliceParams->slice_qp_delta;
237
238 m_idxForTempMVP = 0xFF;
239
240 if (picParams->CollocatedRefPicIndex != 0xFF && picParams->CollocatedRefPicIndex < CODEC_MAX_NUM_REF_FRAME_HEVC)
241 {
242 uint8_t frameIdx = picParams->RefFrameList[picParams->CollocatedRefPicIndex].FrameIdx;
243 m_idxForTempMVP = m_refList[frameIdx]->ucScalingIdx;
244 }
245
246 if (m_pictureCodingType == I_TYPE)
247 {
248 m_currGopIFramePOC = picParams->CurrPicOrderCnt;
249 }
250
251 auto seqParams = m_basicFeature->m_hevcSeqParams;
252 ENCODE_CHK_NULL_RETURN(seqParams);
253
254 slcParams = sliceParams;
255 for (uint32_t s = 0; s < m_basicFeature->m_numSlices; s++, slcParams++)
256 {
257 ENCODE_CHK_STATUS_RETURN(ValidateLowDelayBFrame(slcParams));
258 ENCODE_CHK_STATUS_RETURN(ValidateSameRefInL0L1(slcParams));
259
260 if (m_idxForTempMVP == 0xFF && slcParams->slice_temporal_mvp_enable_flag)
261 {
262 // Temporal reference MV index is invalid and so disable the temporal MVP
263 slcParams->slice_temporal_mvp_enable_flag = false;
264 }
265
266 if (seqParams->sps_temporal_mvp_enable_flag == 0 && slcParams->slice_temporal_mvp_enable_flag == 1)
267 {
268 ENCODE_NORMALMESSAGE("Attention: temporal MVP flag is inconsistent between seq and slice.");
269 slcParams->slice_temporal_mvp_enable_flag = 0;
270 }
271
272 if (!picParams->pps_curr_pic_ref_enabled_flag && m_lowDelay && slcParams->num_ref_idx_l0_active_minus1 == 0
273 && m_currGopIFramePOC != -1 && slcParams->slice_temporal_mvp_enable_flag != 0)
274 {
275 ENCODE_CHK_STATUS_RETURN(ValidateTmvp(slcParams));
276 }
277
278 if (m_lowDelay && !m_sameRefList)
279 {
280 ENCODE_NORMALMESSAGE("Attention: LDB frame but with different L0/L1 list !");
281 }
282 }
283
284 return MOS_STATUS_SUCCESS;
285 }
286
ValidateTmvp(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)287 MOS_STATUS HevcReferenceFrames::ValidateTmvp(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)
288 {
289 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
290
291 ENCODE_FUNC_CALL();
292
293 ENCODE_CHK_NULL_RETURN(slcParams);
294
295 auto idx = m_picIdx[slcParams->RefPicList[0][0].FrameIdx].ucPicIdx;
296
297 if (m_refList[idx]->iFieldOrderCnt[0] == m_currGopIFramePOC)
298 {
299 slcParams->slice_temporal_mvp_enable_flag = 0;
300 }
301
302 return eStatus;
303 }
304
ValidateSameRefInL0L1(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)305 MOS_STATUS HevcReferenceFrames::ValidateSameRefInL0L1(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)
306 {
307 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
308
309 ENCODE_FUNC_CALL();
310
311 ENCODE_CHK_NULL_RETURN(slcParams);
312
313 if (m_sameRefList && slcParams->num_ref_idx_l0_active_minus1 >= slcParams->num_ref_idx_l1_active_minus1)
314 {
315 for (int refIdx = 0; refIdx < slcParams->num_ref_idx_l1_active_minus1 + 1; refIdx++)
316 {
317 CODEC_PICTURE refPicL0 = slcParams->RefPicList[0][refIdx];
318 CODEC_PICTURE refPicL1 = slcParams->RefPicList[1][refIdx];
319
320 if (!CodecHal_PictureIsInvalid(refPicL0) && !CodecHal_PictureIsInvalid(refPicL1) && refPicL0.FrameIdx != refPicL1.FrameIdx)
321 {
322 m_sameRefList = false;
323 break;
324 }
325 }
326 }
327
328 return eStatus;
329 }
330
ValidateLowDelayBFrame(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)331 MOS_STATUS HevcReferenceFrames::ValidateLowDelayBFrame(
332 PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)
333 {
334 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
335
336 ENCODE_FUNC_CALL();
337
338 auto picParams = m_basicFeature->m_hevcPicParams;
339 ENCODE_CHK_NULL_RETURN(picParams);
340 ENCODE_CHK_NULL_RETURN(slcParams);
341
342 if (slcParams->slice_type == encodeHevcPSlice)
343 {
344 m_lowDelay = true;
345 // P slice only has forward l0
346 for (int refIdx = 0; (refIdx < slcParams->num_ref_idx_l0_active_minus1 + 1) && m_lowDelay; refIdx++)
347 {
348 if (refIdx >= CODEC_MAX_NUM_REF_FRAME_HEVC)
349 {
350 break;
351 }
352
353 CODEC_PICTURE refPic = slcParams->RefPicList[0][refIdx];
354 if (!CodecHal_PictureIsInvalid(refPic) && picParams->RefFramePOCList[refPic.FrameIdx] > picParams->CurrPicOrderCnt)
355 {
356 m_lowDelay = false;
357 }
358 }
359 }
360
361 // Examine if now it is B type
362 if (slcParams->slice_type == encodeHevcBSlice)
363 {
364 // forward
365 for (int refIdx = 0; (refIdx < slcParams->num_ref_idx_l0_active_minus1 + 1) && m_lowDelay; refIdx++)
366 {
367 if (refIdx >= CODEC_MAX_NUM_REF_FRAME_HEVC)
368 {
369 break;
370 }
371
372 CODEC_PICTURE refPic = slcParams->RefPicList[0][refIdx];
373 if (!CodecHal_PictureIsInvalid(refPic) && picParams->RefFramePOCList[refPic.FrameIdx] > picParams->CurrPicOrderCnt)
374 {
375 m_lowDelay = false;
376 }
377 }
378
379 // backward
380 for (int refIdx = 0; (refIdx < slcParams->num_ref_idx_l1_active_minus1 + 1) && m_lowDelay; refIdx++)
381 {
382 if (refIdx >= CODEC_MAX_NUM_REF_FRAME_HEVC)
383 {
384 break;
385 }
386
387 CODEC_PICTURE refPic = slcParams->RefPicList[1][refIdx];
388 if (!CodecHal_PictureIsInvalid(refPic) && picParams->RefFramePOCList[refPic.FrameIdx] > picParams->CurrPicOrderCnt)
389 {
390 m_lowDelay = false;
391 }
392 }
393 }
394
395 return eStatus;
396 }
397
IsCurrentUsedAsRef(uint8_t idx)398 bool HevcReferenceFrames::IsCurrentUsedAsRef(uint8_t idx)
399 {
400 ENCODE_FUNC_CALL();
401
402 if (idx < CODEC_MAX_NUM_REF_FRAME_HEVC &&
403 m_picIdx[idx].bValid && m_currUsedRefPic[idx])
404 {
405 return true;
406 }
407 else
408 {
409 return false;
410 }
411 }
412
UpdateRollingIReferenceLocation()413 MOS_STATUS HevcReferenceFrames::UpdateRollingIReferenceLocation()
414 {
415 ENCODE_FUNC_CALL();
416 auto picParams = m_basicFeature->m_hevcPicParams;
417 ENCODE_CHK_NULL_RETURN(picParams);
418 auto sliceParams = m_basicFeature->m_hevcSliceParams;
419 ENCODE_CHK_NULL_RETURN(sliceParams);
420 uint32_t rollingILimit = (picParams->bEnableRollingIntraRefresh == ROLLING_I_ROW) ? MOS_ROUNDUP_DIVIDE(m_basicFeature->m_frameHeight, 32) :
421 (picParams->bEnableRollingIntraRefresh == ROLLING_I_COLUMN) ? MOS_ROUNDUP_DIVIDE(m_basicFeature->m_frameWidth, 32) : 0;
422
423 m_refList[m_currRefIdx]->rollingIntraRefreshedPosition =
424 CodecHal_Clip3(0, rollingILimit, picParams->IntraInsertionLocation + picParams->IntraInsertionSize);
425
426 // Update pic params rolling intra reference location here before cmd buffer is prepared.
427 PCODEC_PICTURE l0RefFrameList = sliceParams->RefPicList[LIST_0];
428 for (uint8_t refIdx = 0; refIdx <= sliceParams->num_ref_idx_l0_active_minus1; refIdx++)
429 {
430 CODEC_PICTURE refPic = l0RefFrameList[refIdx];
431
432 if (!CodecHal_PictureIsInvalid(refPic) && m_picIdx[refPic.FrameIdx].bValid)
433 {
434 uint8_t refPicIdx = m_picIdx[refPic.FrameIdx].ucPicIdx;
435 picParams->RollingIntraReferenceLocation[refIdx] = m_refList[refPicIdx]->rollingIntraRefreshedPosition;
436 }
437 }
438
439 return MOS_STATUS_SUCCESS;
440 }
441
SetSlotForRecNotFiltered(unsigned char & slotForRecNotFiltered)442 MOS_STATUS HevcReferenceFrames::SetSlotForRecNotFiltered(unsigned char &slotForRecNotFiltered)
443 {
444 ENCODE_FUNC_CALL();
445 auto picParams = m_basicFeature->m_hevcPicParams;
446 ENCODE_CHK_NULL_RETURN(picParams);
447
448 MHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams;
449
450 if (m_pictureCodingType != I_TYPE)
451 {
452 for (uint8_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
453 {
454 if (IsCurrentUsedAsRef(i))
455 {
456 uint8_t idx = m_picIdx[i].ucPicIdx;
457
458 uint8_t frameStoreId = m_refIdxMapping[i];
459 pipeBufAddrParams.presReferences[frameStoreId] = &(m_refList[idx]->sRefReconBuffer.OsResource);
460 }
461 }
462 }
463
464 if (picParams->pps_curr_pic_ref_enabled_flag)
465 {
466 // I frame is much simpler
467 if (m_pictureCodingType == I_TYPE)
468 {
469 slotForRecNotFiltered = 0;
470 }
471 // B frame
472 else
473 {
474 unsigned int i;
475
476 for (i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
477 {
478 if (pipeBufAddrParams.presReferences[i] == nullptr)
479 {
480 break;
481 }
482 }
483
484 if (i >= CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC)
485 {
486 slotForRecNotFiltered = CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC;
487 ENCODE_ASSERTMESSAGE("Find no available slot.");
488 return MOS_STATUS_INVALID_PARAMETER;
489 }
490
491 slotForRecNotFiltered = (unsigned char)i;
492 }
493 }
494 return MOS_STATUS_SUCCESS;
495 }
496
MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,HevcReferenceFrames)497 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, HevcReferenceFrames)
498 {
499 ENCODE_FUNC_CALL();
500
501 ENCODE_CHK_NULL_RETURN(m_basicFeature);
502 auto trackedBuf = m_basicFeature->m_trackedBuf;
503 ENCODE_CHK_NULL_RETURN(trackedBuf);
504
505 auto picParams = m_basicFeature->m_hevcPicParams;
506 ENCODE_CHK_NULL_RETURN(picParams);
507
508 auto sliceParams = m_basicFeature->m_hevcSliceParams;
509 ENCODE_CHK_NULL_RETURN(sliceParams);
510
511 auto l0RefFrameList = sliceParams->RefPicList[LIST_0];
512 for (uint8_t refIdx = 0; refIdx <= sliceParams->num_ref_idx_l0_active_minus1; refIdx++)
513 {
514 CODEC_PICTURE refPic = l0RefFrameList[refIdx];
515
516 if (!CodecHal_PictureIsInvalid(refPic) && m_picIdx[refPic.FrameIdx].bValid)
517 {
518 // L0 references
519 uint8_t refPicIdx = m_picIdx[refPic.FrameIdx].ucPicIdx;
520
521 params.refs[refIdx] = (picParams->bUseRawPicForRef) ?
522 &m_refList[refPicIdx]->sRefBuffer.OsResource : &m_refList[refPicIdx]->sRefReconBuffer.OsResource;
523
524 // 4x/8x DS surface for VDEnc
525 uint8_t scaledIdx = m_refList[refPicIdx]->ucScalingIdx;
526 auto vdenc4xDsSurface = trackedBuf->GetSurface(BufferType::ds4xSurface, scaledIdx);
527 ENCODE_CHK_NULL_RETURN(vdenc4xDsSurface);
528 auto vdenc8xDsSurface = trackedBuf->GetSurface(BufferType::ds8xSurface, scaledIdx);
529 ENCODE_CHK_NULL_RETURN(vdenc8xDsSurface);
530 params.refsDsStage2[refIdx] = &vdenc4xDsSurface->OsResource;
531 params.refsDsStage1[refIdx] = &vdenc8xDsSurface->OsResource;
532
533 if (sliceParams->slice_type == encodeHevcPSlice)
534 {
535 params.refs[refIdx + sliceParams->num_ref_idx_l0_active_minus1 + 1] = &m_refList[refPicIdx]->sRefReconBuffer.OsResource;
536 params.refsDsStage2[refIdx + sliceParams->num_ref_idx_l0_active_minus1 + 1] =
537 &vdenc4xDsSurface->OsResource;
538 params.refsDsStage1[refIdx + sliceParams->num_ref_idx_l0_active_minus1 + 1] =
539 &vdenc8xDsSurface->OsResource;
540 }
541 }
542 }
543
544 const CODEC_PICTURE *l1RefFrameList = sliceParams->RefPicList[LIST_1];
545 for (uint8_t refIdx = 0; refIdx <= sliceParams->num_ref_idx_l1_active_minus1; refIdx++)
546 {
547 CODEC_PICTURE refPic = l1RefFrameList[refIdx];
548
549 if (!CodecHal_PictureIsInvalid(refPic) && m_picIdx[refPic.FrameIdx].bValid && encodeHevcPSlice != sliceParams->slice_type)
550 {
551 // L1 references
552 uint8_t refPicIdx = m_picIdx[refPic.FrameIdx].ucPicIdx;
553
554 params.refs[refIdx + sliceParams->num_ref_idx_l0_active_minus1 + 1] = (picParams->bUseRawPicForRef) ?
555 &m_refList[refPicIdx]->sRefBuffer.OsResource : &m_refList[refPicIdx]->sRefReconBuffer.OsResource;
556
557 // 4x/8x DS surface for VDEnc
558 uint8_t scaledIdx = m_refList[refPicIdx]->ucScalingIdx;
559 auto vdenc4xDsSurface = trackedBuf->GetSurface(BufferType::ds4xSurface, scaledIdx);
560 ENCODE_CHK_NULL_RETURN(vdenc4xDsSurface);
561 auto vdenc8xDsSurface = trackedBuf->GetSurface(BufferType::ds8xSurface, scaledIdx);
562 ENCODE_CHK_NULL_RETURN(vdenc8xDsSurface);
563 params.refsDsStage2[refIdx + sliceParams->num_ref_idx_l0_active_minus1 + 1] =
564 &vdenc4xDsSurface->OsResource;
565 params.refsDsStage1[refIdx + sliceParams->num_ref_idx_l0_active_minus1 + 1] =
566 &vdenc8xDsSurface->OsResource;
567 }
568 }
569
570 auto mvTmpBuffer = trackedBuf->GetBuffer(BufferType::mvTemporalBuffer, m_idxForTempMVP);
571 params.colMvTempBuffer[0] = mvTmpBuffer;
572
573 // When partial frame update is enabled, reuse the 4x/8x downscaled surfaces
574 if (false) //m_enablePartialFrameUpdate
575 {
576 CODEC_PICTURE refPic = sliceParams->RefPicList[LIST_0][0];
577
578 if (!CodecHal_PictureIsInvalid(refPic) && m_picIdx[refPic.FrameIdx].bValid)
579 {
580 // L0 references
581 uint8_t refPicIdx = m_picIdx[refPic.FrameIdx].ucPicIdx;
582 // 4x/8x DS surface for VDEnc
583 uint8_t scaledIdx = m_refList[refPicIdx]->ucScalingIdx;
584 auto vdenc4xDsSurface = trackedBuf->GetSurface(BufferType::ds4xSurface, scaledIdx);
585 ENCODE_CHK_NULL_RETURN(vdenc4xDsSurface);
586 auto vdenc8xDsSurface = trackedBuf->GetSurface(BufferType::ds8xSurface, scaledIdx);
587 ENCODE_CHK_NULL_RETURN(vdenc8xDsSurface);
588 params.surfaceDsStage2 = vdenc4xDsSurface;
589 params.surfaceDsStage1 = vdenc8xDsSurface;
590 }
591 }
592
593 params.lowDelayB = m_lowDelay;
594
595 return MOS_STATUS_SUCCESS;
596 }
597
MHW_SETPAR_DECL_SRC(HCP_PIPE_BUF_ADDR_STATE,HevcReferenceFrames)598 MHW_SETPAR_DECL_SRC(HCP_PIPE_BUF_ADDR_STATE, HevcReferenceFrames)
599 {
600 ENCODE_FUNC_CALL();
601
602 ENCODE_CHK_NULL_RETURN(m_basicFeature);
603 auto trackedBuf = m_basicFeature->m_trackedBuf;
604 ENCODE_CHK_NULL_RETURN(trackedBuf);
605 auto picParams = m_basicFeature->m_hevcPicParams;
606 ENCODE_CHK_NULL_RETURN(picParams);
607
608 //add for B frame support
609 if (m_pictureCodingType != I_TYPE)
610 {
611 for (uint8_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
612 {
613 if (i < CODEC_MAX_NUM_REF_FRAME_HEVC &&
614 m_picIdx[i].bValid && m_currUsedRefPic[i])
615 {
616 uint8_t idx = m_picIdx[i].ucPicIdx;
617 //CodecHalGetResourceInfo(m_osInterface, &(m_refList[idx]->sRefReconBuffer));
618
619 uint8_t frameStoreId = m_refIdxMapping[i];
620 params.presReferences[frameStoreId] = (picParams->bUseRawPicForRef) ?
621 &(m_refList[idx]->sRefBuffer.OsResource) : &(m_refList[idx]->sRefReconBuffer.OsResource);
622
623 uint8_t refMbCodeIdx = m_refList[idx]->ucScalingIdx;
624 auto mvTmpBuffer = trackedBuf->GetBuffer(BufferType::mvTemporalBuffer, refMbCodeIdx);
625 ENCODE_CHK_NULL_RETURN(mvTmpBuffer);
626 params.presColMvTempBuffer[frameStoreId] = mvTmpBuffer;
627 }
628 }
629 }
630
631 return MOS_STATUS_SUCCESS;
632 }
633
MHW_SETPAR_DECL_SRC(HCP_SURFACE_STATE,HevcReferenceFrames)634 MHW_SETPAR_DECL_SRC(HCP_SURFACE_STATE, HevcReferenceFrames)
635 {
636 ENCODE_FUNC_CALL();
637
638 #ifdef _MMC_SUPPORTED
639 ENCODE_CHK_NULL_RETURN(m_mmcState);
640 if (m_mmcState->IsMmcEnabled())
641 {
642 ENCODE_CHK_NULL_RETURN(m_basicFeature);
643 auto trackedBuf = m_basicFeature->m_trackedBuf;
644 ENCODE_CHK_NULL_RETURN(trackedBuf);
645
646 params.refsMmcEnable = 0;
647 params.refsMmcType = 0;
648 params.dwCompressionFormat = 0;
649
650 //add for B frame support
651 if (m_pictureCodingType != I_TYPE)
652 {
653 for (uint8_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
654 {
655 if (i < CODEC_MAX_NUM_REF_FRAME_HEVC &&
656 m_picIdx[i].bValid && m_currUsedRefPic[i])
657 {
658 uint8_t idx = m_picIdx[i].ucPicIdx;
659 uint8_t frameStoreId = m_refIdxMapping[i];
660
661 MOS_MEMCOMP_STATE mmcState = MOS_MEMCOMP_DISABLED;
662 ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcState(const_cast<PMOS_SURFACE>(&m_refList[idx]->sRefReconBuffer), &mmcState));
663 params.refsMmcEnable |= (mmcState == MOS_MEMCOMP_RC || mmcState == MOS_MEMCOMP_MC) ? (1 << frameStoreId) : 0;
664 params.refsMmcType |= (mmcState == MOS_MEMCOMP_RC) ? (1 << frameStoreId) : 0;
665 if (mmcState == MOS_MEMCOMP_RC || mmcState == MOS_MEMCOMP_MC)
666 {
667 ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcFormat(const_cast<PMOS_SURFACE>(&m_refList[idx]->sRefReconBuffer), ¶ms.dwCompressionFormat));
668 }
669 }
670 }
671 }
672 }
673 #endif
674
675 return MOS_STATUS_SUCCESS;
676 }
677
678 } // namespace encode
679