1 /*
2 * Copyright (c) 2020-2022, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 //!
24 //! \file decode_hevc_mem_compression.cpp
25 //! \brief Defines the common interface for Hevc decode mmc
26 //! \details The mmc is to handle mmc operations,
27 //! including compression and decompressin of Hevc decode
28 //!
29
30 #include "mos_defs.h"
31 #include "decode_hevc_mem_compression.h"
32
33 namespace decode
34 {
35
HevcDecodeMemComp(CodechalHwInterfaceNext * hwInterface)36 HevcDecodeMemComp::HevcDecodeMemComp(CodechalHwInterfaceNext *hwInterface)
37 {
38 if (hwInterface)
39 {
40 m_osInterface = hwInterface->GetOsInterface();
41 }
42 }
43
SetRefSurfaceMask(HevcBasicFeature & hevcBasicFeature,const PMOS_RESOURCE * presReferences,uint8_t & mmcSkipMask)44 MOS_STATUS HevcDecodeMemComp::SetRefSurfaceMask(
45 HevcBasicFeature &hevcBasicFeature,
46 const PMOS_RESOURCE *presReferences,
47 uint8_t &mmcSkipMask)
48 {
49 if (hevcBasicFeature.m_isSCCIBCMode)
50 {
51 HevcReferenceFrames &refFrames = hevcBasicFeature.m_refFrames;
52 DECODE_ASSERT(hevcBasicFeature.m_hevcPicParams != nullptr);
53 const std::vector<uint8_t> &activeRefList = refFrames.GetActiveReferenceList(*hevcBasicFeature.m_hevcPicParams);
54
55 uint8_t IBCRefIdx = refFrames.m_IBCRefIdx;
56 DECODE_CHK_COND(activeRefList.size() <= IBCRefIdx, "Invalid IBC reference index.");
57 uint8_t IBCFrameIdx = activeRefList[IBCRefIdx];
58
59 uint8_t skipMask = 0;
60 for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
61 {
62 if (presReferences[i] == refFrames.GetReferenceByFrameIndex(IBCFrameIdx))
63 {
64 skipMask |= (1 << i);
65 }
66 }
67 mmcSkipMask = skipMask;
68 DECODE_NORMALMESSAGE("IBC ref index %d, MMC skip mask %d,", IBCRefIdx, skipMask);
69 }
70
71 MOS_MEMCOMP_STATE refMmcState = MOS_MEMCOMP_DISABLED;
72 uint8_t skipMask = 0;
73 for (uint16_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
74 {
75 if (presReferences[i] != nullptr)
76 {
77 DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
78 m_osInterface, presReferences[i], &refMmcState));
79 }
80
81 if (refMmcState == MOS_MEMCOMP_DISABLED)
82 {
83 skipMask |= (1 << i);
84 }
85 }
86 mmcSkipMask |= skipMask;
87 DECODE_NORMALMESSAGE("HEVC MMC skip mask %d\n", mmcSkipMask);
88
89 return MOS_STATUS_SUCCESS;
90 }
91
SetRefSurfaceCompressionFormat(HevcBasicFeature & hevcBasicFeature,const PMOS_RESOURCE * presReferences,uint32_t & mmcCompressionFormat)92 MOS_STATUS HevcDecodeMemComp::SetRefSurfaceCompressionFormat(
93 HevcBasicFeature &hevcBasicFeature,
94 const PMOS_RESOURCE *presReferences,
95 uint32_t &mmcCompressionFormat)
96 {
97 MOS_MEMCOMP_STATE refMmcState = MOS_MEMCOMP_DISABLED;
98 uint32_t compressionFormat = 0;
99 uint32_t refcompressionFormat = 0;
100
101 for (uint16_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
102 {
103 if (presReferences[i] != nullptr)
104 {
105 DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
106 m_osInterface, presReferences[i], &refMmcState));
107
108 if (refMmcState == MOS_MEMCOMP_MC || refMmcState == MOS_MEMCOMP_RC)
109 {
110 DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionFormat(
111 m_osInterface, presReferences[i], &compressionFormat));
112
113 refcompressionFormat = compressionFormat;
114 }
115 }
116 }
117 mmcCompressionFormat = refcompressionFormat;
118 DECODE_NORMALMESSAGE("HEVC reference surface compression format %d\n", mmcCompressionFormat);
119
120 return MOS_STATUS_SUCCESS;
121 }
122
CheckReferenceList(HevcBasicFeature & hevcBasicFeature,MOS_MEMCOMP_STATE & postDeblockSurfMmcState,MOS_MEMCOMP_STATE & preDeblockSurfMmcState,PMOS_RESOURCE * presReferences)123 MOS_STATUS HevcDecodeMemComp::CheckReferenceList(HevcBasicFeature &hevcBasicFeature,
124 MOS_MEMCOMP_STATE &postDeblockSurfMmcState,
125 MOS_MEMCOMP_STATE &preDeblockSurfMmcState,
126 PMOS_RESOURCE *presReferences)
127 {
128 DECODE_FUNC_CALL();
129 DECODE_CHK_NULL(m_osInterface);
130
131 // Disable MMC if self-reference is dectected (mainly for error concealment)
132 if (!hevcBasicFeature.m_refFrames.m_curIsIntra)
133 {
134 if (postDeblockSurfMmcState != MOS_MEMCOMP_DISABLED ||
135 preDeblockSurfMmcState != MOS_MEMCOMP_DISABLED)
136 {
137 DECODE_ASSERT(hevcBasicFeature.m_hevcPicParams);
138 CODEC_HEVC_PIC_PARAMS &hevcPicParams = *(hevcBasicFeature.m_hevcPicParams);
139
140 for (uint8_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
141 {
142 if (hevcPicParams.CurrPic.FrameIdx == hevcPicParams.RefFrameList[i].FrameIdx)
143 {
144 DECODE_NORMALMESSAGE("Self-reference is detected for P/B frames!");
145 postDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
146 preDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
147
148 // Decompress current frame to avoid green corruptions in this error handling case
149 MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED;
150 MOS_SURFACE &destSurface = hevcBasicFeature.m_destSurface;
151 DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
152 m_osInterface, &destSurface.OsResource, &mmcMode));
153 if (mmcMode != MOS_MEMCOMP_DISABLED)
154 {
155 DECODE_CHK_STATUS(m_osInterface->pfnDecompResource(m_osInterface, &destSurface.OsResource));
156 }
157
158 break;
159 }
160 }
161 }
162 }
163
164 // Do surface decompression to make sure the MMC states are consistent in the reference list
165 bool sameMmcStatus = true;
166 MOS_MEMCOMP_STATE mmcModePrev = MOS_MEMCOMP_DISABLED;
167 for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
168 {
169 if (presReferences[i] != nullptr)
170 {
171 MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED;
172 DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
173 m_osInterface, presReferences[i], &mmcMode));
174
175 if (i == 0)
176 {
177 mmcModePrev = mmcMode;
178 }
179 else if (mmcModePrev != mmcMode)
180 {
181 sameMmcStatus = false;
182 break;
183 }
184 }
185 }
186
187 if(!sameMmcStatus)
188 {
189 for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
190 {
191 if (presReferences[i] != nullptr)
192 {
193 MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED;
194 DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
195 m_osInterface, presReferences[i], &mmcMode));
196 if(mmcMode != MOS_MEMCOMP_DISABLED)
197 {
198 m_osInterface->pfnDecompResource(m_osInterface, presReferences[i]);
199 }
200 }
201 }
202 }
203
204 return MOS_STATUS_SUCCESS;
205 }
206
207 }
208