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), &params.dwCompressionFormat));
668                     }
669                 }
670             }
671         }
672     }
673 #endif
674 
675     return MOS_STATUS_SUCCESS;
676 }
677 
678 }  // namespace encode
679